messages = future.get(timeoutMillis, TimeUnit.MILLISECONDS);
if (this.acknowledgeMessages) {
@@ -131,8 +131,7 @@ boolean isHealthyException(ExecutionException e) {
private boolean isHealthyResponseForUnspecifiedSubscription(ExecutionException e) {
Throwable t = e.getCause();
- if (t instanceof ApiException) {
- ApiException aex = (ApiException) t;
+ if (t instanceof ApiException aex) {
Code errorCode = aex.getStatusCode().getCode();
return errorCode == StatusCode.Code.NOT_FOUND || errorCode == Code.PERMISSION_DENIED;
}
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubHealthIndicatorAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubHealthIndicatorAutoConfiguration.java
index 47bb339c90..31cd6b81af 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubHealthIndicatorAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubHealthIndicatorAutoConfiguration.java
@@ -24,6 +24,7 @@
import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration;
import org.springframework.boot.actuate.health.HealthContributor;
import org.springframework.boot.actuate.health.HealthIndicator;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -31,7 +32,6 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;
/**
@@ -39,7 +39,7 @@
*
* @since 1.2.2
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@ConditionalOnClass({HealthIndicator.class, PubSubTemplate.class})
@ConditionalOnBean(PubSubTemplate.class)
@ConditionalOnEnabledHealthIndicator("pubsub")
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubSubscriptionHealthIndicatorAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubSubscriptionHealthIndicatorAutoConfiguration.java
index 6c3ec6b4eb..95f4243ccf 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubSubscriptionHealthIndicatorAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubSubscriptionHealthIndicatorAutoConfiguration.java
@@ -30,19 +30,19 @@
import org.springframework.boot.actuate.autoconfigure.health.CompositeHealthContributorConfiguration;
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
import org.springframework.boot.actuate.health.HealthIndicator;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
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.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
/**
* @since 2.0.6
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@ConditionalOnClass({HealthIndicator.class, MetricServiceClient.class})
@ConditionalOnEnabledHealthIndicator("pubsub-subscriber")
@ConditionalOnProperty({
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/secretmanager/GcpSecretManagerBootstrapConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/secretmanager/GcpSecretManagerBootstrapConfiguration.java
deleted file mode 100644
index 5bc23118c4..0000000000
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/secretmanager/GcpSecretManagerBootstrapConfiguration.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2017-2020 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.cloud.spring.autoconfigure.secretmanager;
-
-import com.google.api.gax.core.CredentialsProvider;
-import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
-import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings;
-import com.google.cloud.spring.core.DefaultCredentialsProvider;
-import com.google.cloud.spring.core.DefaultGcpProjectIdProvider;
-import com.google.cloud.spring.core.GcpProjectIdProvider;
-import com.google.cloud.spring.core.UserAgentHeaderProvider;
-import com.google.cloud.spring.secretmanager.SecretManagerPropertySourceLocator;
-import com.google.cloud.spring.secretmanager.SecretManagerTemplate;
-import java.io.IOException;
-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.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.env.ConfigurableEnvironment;
-
-/**
- * Bootstrap Autoconfiguration for GCP Secret Manager which enables loading secrets as properties
- * into the application {@link org.springframework.core.env.Environment}.
- *
- * @since 1.2.2
- * @deprecated since external resources should be using Spring Boot's Config Data API, more info in
- * here .
- */
-@Deprecated
-@Configuration(proxyBeanMethods = false)
-@EnableConfigurationProperties(GcpSecretManagerProperties.class)
-@ConditionalOnClass({SecretManagerServiceClient.class, SecretManagerTemplate.class})
-@ConditionalOnProperty(value = "spring.cloud.gcp.secretmanager.enabled", matchIfMissing = true)
-public class GcpSecretManagerBootstrapConfiguration {
-
- private final GcpProjectIdProvider gcpProjectIdProvider;
- private final GcpSecretManagerProperties properties;
-
- public GcpSecretManagerBootstrapConfiguration(
- GcpSecretManagerProperties properties, ConfigurableEnvironment configurableEnvironment) {
-
- this.properties = properties;
- this.gcpProjectIdProvider =
- properties.getProjectId() != null
- ? properties::getProjectId
- : new DefaultGcpProjectIdProvider();
- }
-
- @Bean
- @ConditionalOnMissingBean
- public CredentialsProvider googleCredentials(GcpSecretManagerProperties secretManagerProperties)
- throws IOException {
- return new DefaultCredentialsProvider(secretManagerProperties);
- }
-
- @Bean
- @ConditionalOnMissingBean
- public SecretManagerServiceClient secretManagerClient(CredentialsProvider googleCredentials)
- throws IOException {
- SecretManagerServiceSettings settings =
- SecretManagerServiceSettings.newBuilder()
- .setCredentialsProvider(googleCredentials)
- .setHeaderProvider(
- new UserAgentHeaderProvider(GcpSecretManagerBootstrapConfiguration.class))
- .build();
-
- return SecretManagerServiceClient.create(settings);
- }
-
- @Bean
- @ConditionalOnMissingBean
- public SecretManagerTemplate secretManagerTemplate(SecretManagerServiceClient client) {
- return new SecretManagerTemplate(client, this.gcpProjectIdProvider)
- .setAllowDefaultSecretValue(this.properties.isAllowDefaultSecret());
- }
-
- @Bean
- @ConditionalOnMissingBean
- @ConditionalOnProperty(value = "spring.cloud.gcp.secretmanager.legacy", matchIfMissing = true)
- public SecretManagerPropertySourceLocator secretManagerPropertySourceLocator(
- SecretManagerTemplate secretManagerTemplate) {
- return new SecretManagerPropertySourceLocator(secretManagerTemplate, this.gcpProjectIdProvider);
- }
-}
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/security/FirebaseAuthenticationAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/security/FirebaseAuthenticationAutoConfiguration.java
index 46b2144295..da689572de 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/security/FirebaseAuthenticationAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/security/FirebaseAuthenticationAutoConfiguration.java
@@ -22,6 +22,7 @@
import com.google.cloud.spring.security.firebase.FirebaseTokenValidator;
import java.util.ArrayList;
import java.util.List;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -30,7 +31,6 @@
import org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
@@ -44,7 +44,7 @@
/**
* @since 1.2.2
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@ConditionalOnClass(FirebaseTokenValidator.class)
@ConditionalOnProperty(value = "spring.cloud.gcp.security.firebase.enabled", matchIfMissing = true)
@AutoConfigureBefore(OAuth2ResourceServerAutoConfiguration.class)
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/security/IapAuthenticationAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/security/IapAuthenticationAutoConfiguration.java
index 08719bf134..fc8c7751b9 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/security/IapAuthenticationAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/security/IapAuthenticationAutoConfiguration.java
@@ -28,6 +28,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -36,8 +37,6 @@
import org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
@@ -67,15 +66,9 @@
*
*
*
- * If a custom {@link WebSecurityConfigurerAdapter} is present, it must add {@code
- * .oauth2ResourceServer().jwt()} customization to {@link
- * org.springframework.security.config.annotation.web.builders.HttpSecurity} object. If no custom
- * {@link WebSecurityConfigurerAdapter} is found, Spring Boot's default {@code
- * OAuth2ResourceServerWebSecurityConfiguration} will add this customization.
- *
* @since 1.1
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@ConditionalOnProperty(value = "spring.cloud.gcp.security.iap.enabled", matchIfMissing = true)
@ConditionalOnClass({AudienceValidator.class})
@AutoConfigureBefore(OAuth2ResourceServerAutoConfiguration.class)
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/GcpSpannerAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/GcpSpannerAutoConfiguration.java
index f91748f455..eb2648b0dd 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/GcpSpannerAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/GcpSpannerAutoConfiguration.java
@@ -44,18 +44,18 @@
import java.io.IOException;
import java.util.Optional;
import java.util.function.Supplier;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
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.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.data.rest.webmvc.spi.BackendIdConverter;
/** Provides Spring Data classes to use with Cloud Spanner. */
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@AutoConfigureAfter(GcpContextAutoConfiguration.class)
@ConditionalOnProperty(value = "spring.cloud.gcp.spanner.enabled", matchIfMissing = true)
@ConditionalOnClass({
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/GcpSpannerEmulatorAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/GcpSpannerEmulatorAutoConfiguration.java
index e27cbde2a1..ba554ab537 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/GcpSpannerEmulatorAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/GcpSpannerEmulatorAutoConfiguration.java
@@ -23,12 +23,12 @@
import com.google.cloud.spring.core.GcpProjectIdProvider;
import java.io.IOException;
import java.util.Optional;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;
/**
@@ -36,7 +36,7 @@
*
* @since 1.2.3
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@AutoConfigureBefore({GcpSpannerAutoConfiguration.class, GcpContextAutoConfiguration.class})
@EnableConfigurationProperties(GcpSpannerProperties.class)
@ConditionalOnProperty(
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/SpannerRepositoriesAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/SpannerRepositoriesAutoConfiguration.java
index 9b302b4bad..c3a1fa9e43 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/SpannerRepositoriesAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/SpannerRepositoriesAutoConfiguration.java
@@ -19,18 +19,18 @@
import com.google.cloud.spring.data.spanner.repository.SpannerRepository;
import com.google.cloud.spring.data.spanner.repository.config.SpannerRepositoryConfigurationExtension;
import com.google.cloud.spring.data.spanner.repository.support.SpannerRepositoryFactoryBean;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Enables autoconfiguration for {@link
* com.google.cloud.spring.data.spanner.repository.config.EnableSpannerRepositories}.
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@ConditionalOnClass(SpannerRepository.class)
@ConditionalOnMissingBean({
SpannerRepositoryFactoryBean.class,
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/SpannerTransactionManagerAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/SpannerTransactionManagerAutoConfiguration.java
index a38e3a0b5b..380fb419da 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/SpannerTransactionManagerAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/SpannerTransactionManagerAutoConfiguration.java
@@ -20,6 +20,7 @@
import com.google.cloud.spring.data.spanner.core.SpannerTransactionManager;
import java.util.function.Supplier;
import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -27,7 +28,6 @@
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
/**
@@ -35,14 +35,18 @@
*
* @since 1.1
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@ConditionalOnClass(SpannerTransactionManager.class)
@ConditionalOnProperty(value = "spring.cloud.gcp.spanner.enabled", matchIfMissing = true)
@AutoConfigureBefore(TransactionAutoConfiguration.class)
public class SpannerTransactionManagerAutoConfiguration {
+ private SpannerTransactionManagerAutoConfiguration() {
+
+ }
+
/** Config settings. */
- @Configuration(proxyBeanMethods = false)
+ @AutoConfiguration
static class DatabaseClientTransactionManagerConfiguration {
private final Supplier databaseClientProvider;
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/health/SpannerHealthIndicatorAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/health/SpannerHealthIndicatorAutoConfiguration.java
index a4ab723539..f3e9df35d9 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/health/SpannerHealthIndicatorAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/spanner/health/SpannerHealthIndicatorAutoConfiguration.java
@@ -24,6 +24,7 @@
import org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration;
import org.springframework.boot.actuate.health.HealthContributor;
import org.springframework.boot.actuate.health.HealthIndicator;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -31,7 +32,6 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;
/**
@@ -39,7 +39,7 @@
*
* @since 2.0.6
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@ConditionalOnClass({SpannerTemplate.class, HealthIndicator.class})
@ConditionalOnBean(SpannerTemplate.class)
@ConditionalOnEnabledHealthIndicator("spanner")
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/sql/R2dbcCloudSqlEnvironmentPostProcessor.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/sql/R2dbcCloudSqlEnvironmentPostProcessor.java
index 4028e39ddf..45a293416b 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/sql/R2dbcCloudSqlEnvironmentPostProcessor.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/sql/R2dbcCloudSqlEnvironmentPostProcessor.java
@@ -84,10 +84,10 @@ String createUrl(DatabaseType databaseType, GcpCloudSqlProperties sqlProperties)
}
/**
- * Returns {@link DatabaseType} constant based on whether mySQL or postgreSQL R2DBC driver and
+ * Returns {@link DatabaseType} constant based on whether postgresSQL R2DBC driver and
* connector dependencies are present on the classpath. Returns null if Cloud SQL is not enabled
* in Spring Cloud GCP, CredentialFactory is not present or ConnectionFactory (which is used to
- * enable Spring R2DBC auto-configuration) is not present.
+ * enable Spring R2DBC autoconfiguration) is not present.
*
* @param environment environment to post-process
* @return database type
@@ -95,14 +95,10 @@ String createUrl(DatabaseType databaseType, GcpCloudSqlProperties sqlProperties)
DatabaseType getEnabledDatabaseType(ConfigurableEnvironment environment) {
if (isR2dbcEnabled(environment)
&& isOnClasspath("com.google.cloud.sql.CredentialFactory")
- && isOnClasspath("io.r2dbc.spi.ConnectionFactory")) {
- if (isOnClasspath("com.google.cloud.sql.core.GcpConnectionFactoryProviderMysql")
- && isOnClasspath("dev.miku.r2dbc.mysql.MySqlConnectionFactoryProvider")) {
- return DatabaseType.MYSQL;
- } else if (isOnClasspath("com.google.cloud.sql.core.GcpConnectionFactoryProviderPostgres")
- && isOnClasspath("io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider")) {
- return DatabaseType.POSTGRESQL;
- }
+ && isOnClasspath("io.r2dbc.spi.ConnectionFactory")
+ && isOnClasspath("com.google.cloud.sql.core.GcpConnectionFactoryProviderPostgres")
+ && isOnClasspath("io.r2dbc.postgresql.PostgresqlConnectionFactoryProvider")) {
+ return DatabaseType.POSTGRESQL;
}
return null;
}
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/storage/GcpStorageAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/storage/GcpStorageAutoConfiguration.java
index b4df1f886c..7bd6f36fda 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/storage/GcpStorageAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/storage/GcpStorageAutoConfiguration.java
@@ -26,12 +26,12 @@
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import java.io.IOException;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
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.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
@@ -41,7 +41,7 @@
*
* @see GoogleStorageProtocolResolver
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@ConditionalOnClass({GoogleStorageProtocolResolverSettings.class, Storage.class})
@ConditionalOnProperty(value = "spring.cloud.gcp.storage.enabled", matchIfMissing = true)
@EnableConfigurationProperties({GcpProperties.class, GcpStorageProperties.class})
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/StackdriverTraceAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/StackdriverTraceAutoConfiguration.java
index 12ba3f6f57..18ad5f892f 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/StackdriverTraceAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/StackdriverTraceAutoConfiguration.java
@@ -19,15 +19,12 @@
import brave.TracingCustomizer;
import brave.baggage.BaggagePropagation;
import brave.handler.SpanHandler;
-import brave.http.HttpRequestParser;
-import brave.http.HttpTracingCustomizer;
import brave.propagation.B3Propagation;
import brave.propagation.Propagation;
import brave.propagation.stackdriver.StackdriverTracePropagation;
import com.google.api.gax.core.CredentialsProvider;
import com.google.api.gax.core.ExecutorProvider;
import com.google.api.gax.core.FixedExecutorProvider;
-import com.google.cloud.spring.autoconfigure.trace.sleuth.StackdriverHttpRequestParser;
import com.google.cloud.spring.core.DefaultCredentialsProvider;
import com.google.cloud.spring.core.GcpProjectIdProvider;
import com.google.cloud.spring.core.UserAgentHeaderProvider;
@@ -42,15 +39,14 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.actuate.autoconfigure.tracing.BraveAutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
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.context.properties.EnableConfigurationProperties;
-import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
-import org.springframework.cloud.sleuth.autoconfig.brave.instrument.web.BraveHttpConfiguration;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import zipkin2.CheckResult;
import zipkin2.Span;
@@ -64,10 +60,10 @@
import zipkin2.reporter.stackdriver.StackdriverSender.Builder;
/** Config for Stackdriver Trace. */
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@EnableConfigurationProperties({GcpTraceProperties.class})
@ConditionalOnProperty(
- value = {"spring.sleuth.enabled", "spring.cloud.gcp.trace.enabled"},
+ value = {"spring.cloud.gcp.trace.enabled"},
matchIfMissing = true)
@ConditionalOnClass(StackdriverSender.class)
@AutoConfigureBefore(BraveAutoConfiguration.class)
@@ -98,11 +94,11 @@ public class StackdriverTraceAutoConfiguration {
*/
public static final String CUSTOMIZER_BEAN_NAME = "stackdriverTracingCustomizer";
- private GcpProjectIdProvider finalProjectIdProvider;
+ private final GcpProjectIdProvider finalProjectIdProvider;
- private CredentialsProvider finalCredentialsProvider;
+ private final CredentialsProvider finalCredentialsProvider;
- private UserAgentHeaderProvider headerProvider = new UserAgentHeaderProvider(this.getClass());
+ private final UserAgentHeaderProvider headerProvider = new UserAgentHeaderProvider(this.getClass());
private ThreadPoolTaskScheduler defaultTraceSenderThreadPool;
@@ -137,7 +133,7 @@ public SpanHandler stackdriverSpanHandler(
@Bean
@ConditionalOnMissingBean
- ReporterMetrics sleuthReporterMetrics() {
+ ReporterMetrics reporterMetrics() {
return ReporterMetrics.NOOP_METRICS;
}
@@ -260,34 +256,4 @@ public void closeScheduler() {
this.defaultTraceSenderThreadPool.shutdown();
}
}
-
- /** Configuration for Sleuth. */
- @Configuration(proxyBeanMethods = false)
- @ConditionalOnProperty(
- name = "spring.sleuth.http.enabled",
- havingValue = "true",
- matchIfMissing = true)
- @AutoConfigureBefore(BraveHttpConfiguration.class)
- public static class StackdriverTraceHttpAutoconfiguration {
- @Bean
- @ConditionalOnProperty(
- name = "spring.sleuth.http.legacy.enabled",
- havingValue = "false",
- matchIfMissing = true)
- @ConditionalOnMissingBean
- HttpRequestParser stackdriverHttpRequestParser() {
- return new StackdriverHttpRequestParser();
- }
-
- @Bean
- @ConditionalOnProperty(
- name = "spring.sleuth.http.legacy.enabled",
- havingValue = "false",
- matchIfMissing = true)
- @ConditionalOnMissingBean
- HttpTracingCustomizer stackdriverHttpTracingCustomizer(
- HttpRequestParser stackdriverHttpRequestParser) {
- return builder -> builder.clientRequestParser(stackdriverHttpRequestParser);
- }
- }
}
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/pubsub/TracePubSubAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/pubsub/TracePubSubAutoConfiguration.java
index 81b676ce53..a5b16aa97f 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/pubsub/TracePubSubAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/pubsub/TracePubSubAutoConfiguration.java
@@ -22,27 +22,26 @@
import com.google.cloud.spring.autoconfigure.pubsub.GcpPubSubAutoConfiguration;
import com.google.cloud.spring.pubsub.core.publisher.PublisherCustomizer;
import com.google.cloud.spring.pubsub.support.PublisherFactory;
+import io.micrometer.observation.ObservationRegistry;
+import io.micrometer.observation.aop.ObservedAspect;
import org.springframework.beans.factory.BeanFactory;
+import org.springframework.boot.actuate.autoconfigure.tracing.BraveAutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
-import org.springframework.cloud.sleuth.autoconfig.brave.instrument.messaging.BraveMessagingAutoConfiguration;
-import org.springframework.cloud.sleuth.brave.instrument.messaging.ConditionalOnMessagingEnabled;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
-@Configuration(proxyBeanMethods = false)
-@ConditionalOnMessagingEnabled
+@AutoConfiguration
@ConditionalOnBean(Tracing.class)
-@ConditionalOnProperty(value = "spring.cloud.gcp.trace.pubsub.enabled", matchIfMissing = false)
+@ConditionalOnProperty(value = "spring.cloud.gcp.trace.pubsub.enabled")
@ConditionalOnClass({PublisherFactory.class, MessagingTracing.class})
-@AutoConfigureAfter({BraveAutoConfiguration.class, BraveMessagingAutoConfiguration.class})
+@AutoConfigureAfter({BraveAutoConfiguration.class})
@AutoConfigureBefore(GcpPubSubAutoConfiguration.class)
class TracePubSubAutoConfiguration {
@@ -63,8 +62,22 @@ PubSubTracing pubSubTracing(MessagingTracing messagingTracing) {
PublisherCustomizer tracePublisherCustomizer(PubSubTracing pubSubTracing) {
TraceHelper helper = new TraceHelper(pubSubTracing);
- return (Publisher.Builder publisherBuilder, String topic) -> {
- publisherBuilder.setTransform(msg -> helper.instrumentMessage(msg, topic));
- };
+ return (Publisher.Builder publisherBuilder, String topic) ->
+ publisherBuilder.setTransform(msg -> helper.instrumentMessage(msg, topic));
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public MessagingTracing messagingTracing(Tracing tracing) {
+ return MessagingTracing.create(tracing);
+ }
+
+ // To have the @Observed support we need to register this aspect
+ // Refers to https://spring.io/blog/2022/10/12/observability-with-spring-boot-3
+ // for more info.
+ @Bean
+ @ConditionalOnMissingBean
+ ObservedAspect observedAspect(ObservationRegistry observationRegistry) {
+ return new ObservedAspect(observationRegistry);
}
}
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/pubsub/TracingSubscriberFactory.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/pubsub/TracingSubscriberFactory.java
index 6179f28843..e30e526424 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/pubsub/TracingSubscriberFactory.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/pubsub/TracingSubscriberFactory.java
@@ -49,11 +49,6 @@ public PullRequest createPullRequest(
return delegate.createPullRequest(subscriptionName, maxMessages, returnImmediately);
}
- @Override
- public SubscriberStub createSubscriberStub() {
- return pubSubTracing.subscriberStub(delegate.createSubscriberStub());
- }
-
@Override
public SubscriberStub createSubscriberStub(String subscriptionName) {
return pubSubTracing.subscriberStub(delegate.createSubscriberStub(subscriptionName));
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/sleuth/StackdriverHttpRequestParser.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/sleuth/StackdriverHttpRequestParser.java
deleted file mode 100644
index 9b12f3ac3d..0000000000
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/sleuth/StackdriverHttpRequestParser.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2017-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.cloud.spring.autoconfigure.trace.sleuth;
-
-import brave.SpanCustomizer;
-import brave.http.HttpRequest;
-import brave.http.HttpRequestParser;
-import brave.http.HttpTags;
-import brave.propagation.TraceContext;
-import java.net.URI;
-
-/**
- * An {@link HttpRequestParser} that fills information for Stackdriver Trace.
- *
- * Based on {@code org.springframework.cloud.sleuth.instrument.web.SleuthHttpClientParser}.
- */
-public class StackdriverHttpRequestParser implements HttpRequestParser {
-
- @Override
- public void parse(HttpRequest request, TraceContext context, SpanCustomizer customizer) {
- HttpRequestParser.DEFAULT.parse(request, context, customizer);
- HttpTags.URL.tag(request, context, customizer);
- HttpTags.ROUTE.tag(request, context, customizer);
-
- String url = request.url();
- URI uri = URI.create(url);
- if (uri.getHost() != null) {
- customizer.tag("http.host", uri.getHost());
- }
- }
-}
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/sleuth/package-info.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/sleuth/package-info.java
deleted file mode 100644
index f03ab1791a..0000000000
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/trace/sleuth/package-info.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2018-2022 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Auto-configuration for Spring Cloud GCP Trace module related to Sleuth and Stackdriver
- * integration.
- */
-package com.google.cloud.spring.autoconfigure.trace.sleuth;
diff --git a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/vision/CloudVisionAutoConfiguration.java b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/vision/CloudVisionAutoConfiguration.java
index c4f2f200b0..d280928533 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/vision/CloudVisionAutoConfiguration.java
+++ b/spring-cloud-gcp-autoconfigure/src/main/java/com/google/cloud/spring/autoconfigure/vision/CloudVisionAutoConfiguration.java
@@ -27,12 +27,12 @@
import java.io.IOException;
import java.util.concurrent.Executor;
import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
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.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
@@ -40,7 +40,7 @@
*
* @since 1.1
*/
-@Configuration(proxyBeanMethods = false)
+@AutoConfiguration
@EnableConfigurationProperties(CloudVisionProperties.class)
@ConditionalOnClass(CloudVisionTemplate.class)
@ConditionalOnProperty(value = "spring.cloud.gcp.vision.enabled", matchIfMissing = true)
diff --git a/spring-cloud-gcp-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-cloud-gcp-autoconfigure/src/main/resources/META-INF/spring.factories
index a3ff19996e..170b2869c6 100644
--- a/spring-cloud-gcp-autoconfigure/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-gcp-autoconfigure/src/main/resources/META-INF/spring.factories
@@ -1,37 +1,5 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-com.google.cloud.spring.autoconfigure.pubsub.GcpPubSubEmulatorAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.core.GcpContextAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.logging.StackdriverLoggingAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.pubsub.GcpPubSubAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.pubsub.GcpPubSubReactiveAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.spanner.GcpSpannerAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.spanner.GcpSpannerEmulatorAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.spanner.health.SpannerHealthIndicatorAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.spanner.SpannerTransactionManagerAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.datastore.GcpDatastoreAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.firestore.GcpFirestoreAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.firestore.FirestoreTransactionManagerAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.firestore.GcpFirestoreEmulatorAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.datastore.health.DatastoreHealthIndicatorAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.storage.GcpStorageAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.trace.StackdriverTraceAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.trace.pubsub.TracePubSubAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.datastore.DatastoreRepositoriesAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.spanner.SpannerRepositoriesAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.security.IapAuthenticationAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.security.FirebaseAuthenticationAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.vision.CloudVisionAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.datastore.GcpDatastoreEmulatorAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.bigquery.GcpBigQueryAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.datastore.DatastoreTransactionManagerAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.firestore.FirestoreRepositoriesAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.pubsub.health.PubSubSubscriptionHealthIndicatorAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.pubsub.health.PubSubHealthIndicatorAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.metrics.GcpStackdriverMetricsAutoConfiguration,\
-com.google.cloud.spring.autoconfigure.kms.GcpKmsAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
-com.google.cloud.spring.autoconfigure.config.GcpConfigBootstrapConfiguration,\
-com.google.cloud.spring.autoconfigure.secretmanager.GcpSecretManagerBootstrapConfiguration
+com.google.cloud.spring.autoconfigure.config.GcpConfigBootstrapConfiguration
org.springframework.boot.env.EnvironmentPostProcessor=\
com.google.cloud.spring.autoconfigure.sql.CloudSqlEnvironmentPostProcessor,\
com.google.cloud.spring.autoconfigure.sql.R2dbcCloudSqlEnvironmentPostProcessor,\
diff --git a/spring-cloud-gcp-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-gcp-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000..99c6d6dffd
--- /dev/null
+++ b/spring-cloud-gcp-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,30 @@
+com.google.cloud.spring.autoconfigure.bigquery.GcpBigQueryAutoConfiguration
+com.google.cloud.spring.autoconfigure.core.GcpContextAutoConfiguration
+com.google.cloud.spring.autoconfigure.datastore.DatastoreRepositoriesAutoConfiguration
+com.google.cloud.spring.autoconfigure.datastore.GcpDatastoreAutoConfiguration
+com.google.cloud.spring.autoconfigure.datastore.GcpDatastoreEmulatorAutoConfiguration
+com.google.cloud.spring.autoconfigure.datastore.DatastoreTransactionManagerAutoConfiguration
+com.google.cloud.spring.autoconfigure.datastore.health.DatastoreHealthIndicatorAutoConfiguration
+com.google.cloud.spring.autoconfigure.firestore.FirestoreTransactionManagerAutoConfiguration
+com.google.cloud.spring.autoconfigure.firestore.GcpFirestoreAutoConfiguration
+com.google.cloud.spring.autoconfigure.firestore.GcpFirestoreEmulatorAutoConfiguration
+com.google.cloud.spring.autoconfigure.firestore.FirestoreRepositoriesAutoConfiguration
+com.google.cloud.spring.autoconfigure.kms.GcpKmsAutoConfiguration
+com.google.cloud.spring.autoconfigure.metrics.GcpStackdriverMetricsAutoConfiguration
+com.google.cloud.spring.autoconfigure.pubsub.GcpPubSubAutoConfiguration
+com.google.cloud.spring.autoconfigure.pubsub.GcpPubSubEmulatorAutoConfiguration
+com.google.cloud.spring.autoconfigure.pubsub.GcpPubSubReactiveAutoConfiguration
+com.google.cloud.spring.autoconfigure.pubsub.health.PubSubHealthIndicatorAutoConfiguration
+com.google.cloud.spring.autoconfigure.pubsub.health.PubSubSubscriptionHealthIndicatorAutoConfiguration
+com.google.cloud.spring.autoconfigure.logging.StackdriverLoggingAutoConfiguration
+com.google.cloud.spring.autoconfigure.security.FirebaseAuthenticationAutoConfiguration
+com.google.cloud.spring.autoconfigure.security.IapAuthenticationAutoConfiguration
+com.google.cloud.spring.autoconfigure.spanner.GcpSpannerAutoConfiguration
+com.google.cloud.spring.autoconfigure.spanner.GcpSpannerEmulatorAutoConfiguration
+com.google.cloud.spring.autoconfigure.spanner.SpannerRepositoriesAutoConfiguration
+com.google.cloud.spring.autoconfigure.spanner.SpannerTransactionManagerAutoConfiguration
+com.google.cloud.spring.autoconfigure.spanner.health.SpannerHealthIndicatorAutoConfiguration
+com.google.cloud.spring.autoconfigure.storage.GcpStorageAutoConfiguration
+com.google.cloud.spring.autoconfigure.trace.StackdriverTraceAutoConfiguration
+com.google.cloud.spring.autoconfigure.trace.pubsub.TracePubSubAutoConfiguration
+com.google.cloud.spring.autoconfigure.vision.CloudVisionAutoConfiguration
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/datastore/TestRepository.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/datastore/TestRepository.java
index 0607e35984..ac873e3515 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/datastore/TestRepository.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/datastore/TestRepository.java
@@ -19,4 +19,4 @@
import com.google.cloud.spring.data.datastore.repository.DatastoreRepository;
/** A repository for testing instantiation. */
-public interface TestRepository extends DatastoreRepository {}
+public interface TestRepository extends DatastoreRepository {}
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/logging/StackdriverLoggingAutoConfigurationTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/logging/StackdriverLoggingAutoConfigurationTests.java
index 3cd6785b76..f23921b224 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/logging/StackdriverLoggingAutoConfigurationTests.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/logging/StackdriverLoggingAutoConfigurationTests.java
@@ -24,24 +24,28 @@
import com.google.cloud.spring.autoconfigure.core.GcpContextAutoConfiguration;
import com.google.cloud.spring.autoconfigure.trace.StackdriverTraceAutoConfiguration;
import com.google.cloud.spring.logging.TraceIdLoggingWebMvcInterceptor;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
-import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
import org.springframework.context.annotation.Bean;
import zipkin2.reporter.Reporter;
/** Tests for auto-config. */
class StackdriverLoggingAutoConfigurationTests {
- private WebApplicationContextRunner contextRunner =
- new WebApplicationContextRunner()
- .withUserConfiguration(TestConfiguration.class)
- .withConfiguration(
- AutoConfigurations.of(
- StackdriverLoggingAutoConfiguration.class, GcpContextAutoConfiguration.class));
+ private WebApplicationContextRunner contextRunner;
+
+ @BeforeEach
+ void init() {
+ contextRunner = new WebApplicationContextRunner()
+ .withUserConfiguration(TestConfiguration.class)
+ .withConfiguration(
+ AutoConfigurations.of(
+ StackdriverLoggingAutoConfiguration.class, GcpContextAutoConfiguration.class));
+ }
@Test
void testDisabledConfiguration() {
@@ -87,11 +91,9 @@ void testRegularConfiguration() {
}
@Test
- void testWithSleuth() {
+ void testWithStackdriverTraceAutoConfiguration() {
this.contextRunner
- .withConfiguration(
- AutoConfigurations.of(
- StackdriverTraceAutoConfiguration.class, BraveAutoConfiguration.class))
+ .withConfiguration(AutoConfigurations.of(StackdriverTraceAutoConfiguration.class))
.withPropertyValues("spring.cloud.gcp.project-id=pop-1")
.run(
context ->
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/GcpPubSubAutoConfigurationTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/GcpPubSubAutoConfigurationTests.java
index 61440be6e1..3f18d1e72c 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/GcpPubSubAutoConfigurationTests.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/GcpPubSubAutoConfigurationTests.java
@@ -38,6 +38,7 @@
import com.google.cloud.spring.pubsub.support.CachingPublisherFactory;
import com.google.cloud.spring.pubsub.support.DefaultPublisherFactory;
import com.google.cloud.spring.pubsub.support.DefaultSubscriberFactory;
+import com.google.cloud.spring.pubsub.support.PubSubSubscriptionUtils;
import com.google.cloud.spring.pubsub.support.PublisherFactory;
import com.google.pubsub.v1.ProjectSubscriptionName;
import java.util.List;
@@ -774,7 +775,7 @@ void retrySettings_globalConfigurationSet() {
GcpProjectIdProvider projectIdProvider = ctx.getBean(GcpProjectIdProvider.class);
PubSubConfiguration.Retry retrySettings =
gcpPubSubProperties.computeSubscriberRetrySettings(
- "subscription-name", projectIdProvider.getProjectId());
+ ProjectSubscriptionName.of(projectIdProvider.getProjectId(), "subscription-name"));
assertThat(retrySettings.getTotalTimeoutSeconds()).isEqualTo(1L);
assertThat(retrySettings.getInitialRetryDelaySeconds()).isEqualTo(2L);
assertThat(retrySettings.getRetryDelayMultiplier()).isEqualTo(3);
@@ -824,8 +825,7 @@ void retrySettings_selectiveConfigurationSet() {
GcpProjectIdProvider projectIdProvider = ctx.getBean(GcpProjectIdProvider.class);
PubSubConfiguration.Retry retrySettings =
gcpPubSubProperties.computeSubscriberRetrySettings(
- "subscription-name", projectIdProvider.getProjectId());
-
+ ProjectSubscriptionName.of(projectIdProvider.getProjectId(), "subscription-name"));
assertThat(retrySettings.getTotalTimeoutSeconds()).isEqualTo(1L);
assertThat(retrySettings.getInitialRetryDelaySeconds()).isEqualTo(2L);
assertThat(retrySettings.getRetryDelayMultiplier()).isEqualTo(3);
@@ -891,7 +891,7 @@ void retrySettings_globalAndSelectiveConfigurationSet_selectiveTakesPrecedence()
// property set
PubSubConfiguration.Retry retrySettings =
gcpPubSubProperties.computeSubscriberRetrySettings(
- "subscription-name", projectIdProvider.getProjectId());
+ ProjectSubscriptionName.of(projectIdProvider.getProjectId(), "subscription-name"));
assertThat(gcpPubSubProperties.getFullyQualifiedSubscriberProperties())
.containsKey(ProjectSubscriptionName.parse(
"projects/fake project/subscriptions/subscription-name"));
@@ -909,7 +909,8 @@ void retrySettings_globalAndSelectiveConfigurationSet_selectiveTakesPrecedence()
// property set
PubSubConfiguration.Retry retrySettingsForOtherSubscriber =
gcpPubSubProperties
- .getSubscriber("other", projectIdProvider.getProjectId())
+ .getSubscriptionProperties(PubSubSubscriptionUtils
+ .toProjectSubscriptionName("other", projectIdProvider.getProjectId()))
.getRetry();
assertThat(retrySettingsForOtherSubscriber.getTotalTimeoutSeconds()).isEqualTo(10L);
assertThat(retrySettingsForOtherSubscriber.getInitialRetryDelaySeconds()).isEqualTo(
@@ -985,8 +986,7 @@ void retrySettings_globalAndDifferentSelectiveConfigurationSet_pickGlobal() {
PubSubConfiguration.Retry retrySettings =
gcpPubSubProperties.computeSubscriberRetrySettings(
- "subscription-name", projectIdProvider.getProjectId());
-
+ ProjectSubscriptionName.of(projectIdProvider.getProjectId(), "subscription-name"));
assertThat(retrySettings.getTotalTimeoutSeconds()).isEqualTo(10L);
assertThat(retrySettings.getInitialRetryDelaySeconds()).isEqualTo(10L);
assertThat(retrySettings.getRetryDelayMultiplier()).isEqualTo(10);
@@ -1035,7 +1035,7 @@ void retrySettings_subsetOfProperties_pickGlobalWhenSelectiveNotSpecified() {
GcpProjectIdProvider projectIdProvider = ctx.getBean(GcpProjectIdProvider.class);
PubSubConfiguration.Retry retry =
gcpPubSubProperties.computeSubscriberRetrySettings(
- "subscription-name", projectIdProvider.getProjectId());
+ ProjectSubscriptionName.of(projectIdProvider.getProjectId(), "subscription-name"));
assertThat(retry.getTotalTimeoutSeconds()).isEqualTo(10L);
assertThat(retry.getInitialRetryDelaySeconds()).isEqualTo(2L);
assertThat(retry.getRetryDelayMultiplier()).isEqualTo(3);
@@ -1140,7 +1140,9 @@ void flowControlSettings_selectiveConfigurationSet() {
PubSubConfiguration.FlowControl flowControl =
gcpPubSubProperties
- .getSubscriber("subscription-name", projectIdProvider.getProjectId())
+ .getSubscriptionProperties(
+ PubSubSubscriptionUtils
+ .toProjectSubscriptionName("subscription-name", projectIdProvider.getProjectId()))
.getFlowControl();
assertThat(flowControl.getMaxOutstandingElementCount()).isEqualTo(11L);
assertThat(flowControl.getMaxOutstandingRequestBytes()).isEqualTo(12L);
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/GcpPubSubReactiveAutoConfigurationTest.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/GcpPubSubReactiveAutoConfigurationTest.java
index f1d7e93d20..52f9802b62 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/GcpPubSubReactiveAutoConfigurationTest.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/GcpPubSubReactiveAutoConfigurationTest.java
@@ -28,6 +28,7 @@
import com.google.cloud.spring.pubsub.reactive.PubSubReactiveFactory;
import com.google.cloud.spring.pubsub.support.AcknowledgeablePubsubMessage;
import java.util.Arrays;
+import java.util.concurrent.CompletableFuture;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -41,7 +42,6 @@
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.annotation.AsyncResult;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;
import reactor.test.StepVerifier;
@@ -130,7 +130,7 @@ private void setUpThreadPrefixVerification(String threadPrefix) {
arg -> {
assertThat(Thread.currentThread().getName()).startsWith(threadPrefix);
- return AsyncResult.forValue(Arrays.asList(mockMessage, mockMessage, mockMessage));
+ return CompletableFuture.completedFuture(Arrays.asList(mockMessage, mockMessage, mockMessage));
});
}
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubHealthIndicatorAutoConfigurationTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubHealthIndicatorAutoConfigurationTests.java
index 2616428fa1..97504d05f5 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubHealthIndicatorAutoConfigurationTests.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubHealthIndicatorAutoConfigurationTests.java
@@ -17,21 +17,16 @@
package com.google.cloud.spring.autoconfigure.pubsub.health;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.api.gax.core.CredentialsProvider;
-import com.google.api.gax.grpc.GrpcStatusCode;
-import com.google.api.gax.rpc.ApiException;
import com.google.auth.Credentials;
import com.google.cloud.spring.autoconfigure.pubsub.GcpPubSubAutoConfiguration;
import com.google.cloud.spring.core.GcpProjectIdProvider;
@@ -39,17 +34,14 @@
import com.google.cloud.spring.pubsub.support.AcknowledgeablePubsubMessage;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern;
import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.actuate.health.CompositeHealthContributor;
+import org.springframework.boot.actuate.health.NamedContributor;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.util.concurrent.ListenableFuture;
/** Tests for Pub/Sub Health Indicator autoconfiguration. */
class PubSubHealthIndicatorAutoConfigurationTests {
@@ -57,7 +49,7 @@ class PubSubHealthIndicatorAutoConfigurationTests {
private static final Pattern UUID_PATTERN =
Pattern.compile("spring-cloud-gcp-healthcheck-[a-f0-9]{8}(-[a-f0-9]{4}){4}[a-f0-9]{8}");
- private ApplicationContextRunner baseContextRunner =
+ private final ApplicationContextRunner baseContextRunner =
new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(
@@ -111,7 +103,7 @@ void healthIndicatorPresent_customConfig() {
void compositeHealthIndicatorPresentMultiplePubSubTemplate() throws Exception {
PubSubTemplate mockPubSubTemplate1 = mock(PubSubTemplate.class);
PubSubTemplate mockPubSubTemplate2 = mock(PubSubTemplate.class);
- ListenableFuture> future = mock(ListenableFuture.class);
+ CompletableFuture> future = mock(CompletableFuture.class);
when(future.get(anyLong(), any())).thenReturn(Collections.emptyList());
when(mockPubSubTemplate1.pullAsync(anyString(), anyInt(), anyBoolean())).thenReturn(future);
@@ -134,7 +126,7 @@ void compositeHealthIndicatorPresentMultiplePubSubTemplate() throws Exception {
ctx.getBean("pubSubHealthContributor", CompositeHealthContributor.class);
assertThat(healthContributor).isNotNull();
assertThat(healthContributor.stream()).hasSize(2);
- assertThat(healthContributor.stream().map(c -> c.getName()))
+ assertThat(healthContributor.stream().map(NamedContributor::getName))
.containsExactlyInAnyOrder("pubSubTemplate1", "pubSubTemplate2");
});
}
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubHealthIndicatorTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubHealthIndicatorTests.java
index f6b6ce238d..24ee9821cb 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubHealthIndicatorTests.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/health/PubSubHealthIndicatorTests.java
@@ -17,7 +17,6 @@
package com.google.cloud.spring.autoconfigure.pubsub.health;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -34,9 +33,9 @@
import com.google.cloud.spring.pubsub.core.PubSubTemplate;
import com.google.cloud.spring.pubsub.support.AcknowledgeablePubsubMessage;
import io.grpc.Status.Code;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.Test;
@@ -45,9 +44,7 @@
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
-import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.boot.actuate.health.Status;
-import org.springframework.util.concurrent.ListenableFuture;
/** Tests for the Pub/Sub Health Indicator. */
@ExtendWith(MockitoExtension.class)
@@ -55,7 +52,8 @@ class PubSubHealthIndicatorTests {
@Mock private PubSubTemplate pubSubTemplate;
- @Mock ListenableFuture> future;
+ @Mock
+ CompletableFuture> future;
@Test
void healthUp_customSubscription() throws Exception {
@@ -70,7 +68,7 @@ void healthUp_customSubscription() throws Exception {
@Test
void acknowledgeEnabled() throws Exception {
AcknowledgeablePubsubMessage msg = mock(AcknowledgeablePubsubMessage.class);
- when(future.get(anyLong(), any())).thenReturn(Arrays.asList(msg));
+ when(future.get(anyLong(), any())).thenReturn(List.of(msg));
when(pubSubTemplate.pullAsync(anyString(), anyInt(), anyBoolean())).thenReturn(future);
PubSubHealthIndicator healthIndicator =
@@ -82,7 +80,7 @@ void acknowledgeEnabled() throws Exception {
@Test
void acknowledgeDisabled() throws Exception {
AcknowledgeablePubsubMessage msg = mock(AcknowledgeablePubsubMessage.class);
- when(future.get(anyLong(), any())).thenReturn(Arrays.asList(msg));
+ when(future.get(anyLong(), any())).thenReturn(List.of(msg));
when(pubSubTemplate.pullAsync(anyString(), anyInt(), anyBoolean())).thenReturn(future);
PubSubHealthIndicator healthIndicator =
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubAutoConfigurationIntegrationTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubAutoConfigurationIntegrationTests.java
index c070fc82c0..017d518a47 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubAutoConfigurationIntegrationTests.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubAutoConfigurationIntegrationTests.java
@@ -50,10 +50,10 @@ class PubSubAutoConfigurationIntegrationTests {
private static GcpProjectIdProvider projectIdProvider;
- private String fullSubscriptionNameSub1 = "projects/" + projectIdProvider.getProjectId() + "/subscriptions/test-sub-1";
- private String fullSubscriptionNameSub2 = "projects/" + projectIdProvider.getProjectId() + "/subscriptions/test-sub-2";
+ private final String fullSubscriptionNameSub1 = "projects/" + projectIdProvider.getProjectId() + "/subscriptions/test-sub-1";
+ private final String fullSubscriptionNameSub2 = "projects/" + projectIdProvider.getProjectId() + "/subscriptions/test-sub-2";
- private ApplicationContextRunner contextRunner =
+ private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withPropertyValues(
"spring.cloud.gcp.pubsub.subscriber.retryableCodes=INTERNAL",
@@ -125,7 +125,7 @@ void testPull() {
.build();
PubSubConfiguration.Retry retry =
gcpPubSubProperties.computeSubscriberRetrySettings(
- subscriptionName, projectId);
+ ProjectSubscriptionName.of(projectId, subscriptionName));
assertThat(retry.getTotalTimeoutSeconds()).isEqualTo(600L);
assertThat(retry.getInitialRetryDelaySeconds()).isEqualTo(100L);
assertThat(retry.getRetryDelayMultiplier()).isEqualTo(1.3);
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubChannelAdaptersIntegrationTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubChannelAdaptersIntegrationTests.java
index 7456333e24..05c0591af0 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubChannelAdaptersIntegrationTests.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubChannelAdaptersIntegrationTests.java
@@ -18,7 +18,8 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.times;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import com.google.cloud.spring.autoconfigure.core.GcpContextAutoConfiguration;
@@ -31,6 +32,7 @@
import com.google.cloud.spring.pubsub.integration.AckMode;
import com.google.cloud.spring.pubsub.integration.inbound.PubSubInboundChannelAdapter;
import com.google.cloud.spring.pubsub.integration.outbound.PubSubMessageHandler;
+import com.google.cloud.spring.pubsub.integration.outbound.PubSubMessageHandler.SuccessCallback;
import com.google.cloud.spring.pubsub.support.BasicAcknowledgeablePubsubMessage;
import com.google.cloud.spring.pubsub.support.GcpPubSubHeaders;
import java.io.IOException;
@@ -45,7 +47,6 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
-import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@@ -61,7 +62,6 @@
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.messaging.support.MessageBuilder;
-import org.springframework.util.concurrent.ListenableFutureCallback;
/** Tests for Pub/Sub channel adapters. */
@EnabledIfSystemProperty(named = "it.pubsub", matches = "true")
@@ -82,7 +82,7 @@ static void enableTests() throws IOException {
pubSubAdmin =
new PubSubAdmin(
new DefaultGcpProjectIdProvider(),
- new DefaultCredentialsProvider(() -> new Credentials()));
+ new DefaultCredentialsProvider(Credentials::new));
}
@BeforeEach
@@ -120,7 +120,7 @@ void sendAndReceiveMessageAsString() {
.run(
context -> {
Map headers = new HashMap<>();
- // Only String values for now..
+ // Only String values for now.
headers.put("storm", "lift your skinny fists");
headers.put("static", "lift your skinny fists");
headers.put("sleep", "lift your skinny fists");
@@ -141,9 +141,9 @@ void sendAndReceiveMessageAsString() {
assertThat(payload).isEqualTo("I am a message (sendAndReceiveMessageAsString).");
assertThat(message.getHeaders()).hasSize(6);
- assertThat(message.getHeaders().get("storm")).isEqualTo("lift your skinny fists");
- assertThat(message.getHeaders().get("static")).isEqualTo("lift your skinny fists");
- assertThat(message.getHeaders().get("sleep")).isEqualTo("lift your skinny fists");
+ assertThat(message.getHeaders()).containsEntry("storm", "lift your skinny fists");
+ assertThat(message.getHeaders()).containsEntry("static", "lift your skinny fists");
+ assertThat(message.getHeaders()).containsEntry("sleep", "lift your skinny fists");
assertThat(message.getHeaders().get(GcpPubSubHeaders.ORIGINAL_MESSAGE)).isNotNull();
});
}
@@ -259,7 +259,6 @@ void sendAndReceiveMessageAutoAckWithFailure() {
}
@Test
- @SuppressWarnings("deprecation")
void sendAndReceiveMessageManualAckThroughAcknowledgementHeader() {
this.contextRunner
.withUserConfiguration(PollableConfiguration.class, CommonConfiguration.class)
@@ -295,16 +294,8 @@ void sendAndReceiveMessagePublishCallback() {
.withUserConfiguration(PollableConfiguration.class, CommonConfiguration.class)
.run(
context -> {
- ListenableFutureCallback callbackSpy =
- Mockito.spy(
- new ListenableFutureCallback() {
- @Override
- public void onFailure(Throwable ex) {}
-
- @Override
- public void onSuccess(String result) {}
- });
- context.getBean(PubSubMessageHandler.class).setPublishCallback(callbackSpy);
+ SuccessCallback successCallback = mock(SuccessCallback.class);
+ context.getBean(PubSubMessageHandler.class).setSuccessCallback(successCallback);
context
.getBean("inputChannel", MessageChannel.class)
.send(
@@ -317,9 +308,11 @@ public void onSuccess(String result) {}
.getBean("outputChannel", PollableChannel.class)
.receive(RECEIVE_TIMEOUT_MS);
assertThat(message).isNotNull();
+
Awaitility.await()
.atMost(1, TimeUnit.SECONDS)
- .untilAsserted(() -> verify(callbackSpy, times(1)).onSuccess(any()));
+ .untilAsserted(() ->
+ verify(successCallback).onSuccess(anyString(), any()));
});
}
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubTemplateDocumentationIntegrationTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubTemplateDocumentationIntegrationTests.java
index 0a46535ea4..165331ab7b 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubTemplateDocumentationIntegrationTests.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubTemplateDocumentationIntegrationTests.java
@@ -43,7 +43,6 @@
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
@@ -53,13 +52,12 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.support.GenericMessage;
-import org.springframework.util.concurrent.ListenableFutureCallback;
/** Documentation tests for Pub/Sub. */
@EnabledIfSystemProperty(named = "it.pubsub-docs", matches = "true")
class PubSubTemplateDocumentationIntegrationTests {
- private ApplicationContextRunner contextRunner =
+ private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withPropertyValues(
"spring.cloud.gcp.pubsub.subscriber.max-ack-extension-period=0",
@@ -179,12 +177,12 @@ private void pubSubTest(PubSubTest pubSubTest, Class... configClass) {
List subscriptions =
pubSubAdmin.listSubscriptions().stream()
.map(Subscription::getName)
- .collect(Collectors.toList());
+ .toList();
// end::list_subscriptions[]
// tag::list_topics[]
List topics =
- pubSubAdmin.listTopics().stream().map(Topic::getName).collect(Collectors.toList());
+ pubSubAdmin.listTopics().stream().map(Topic::getName).toList();
// end::list_topics[]
pubSubAdmin.deleteSubscription(subscriptionName);
@@ -372,14 +370,8 @@ public PubSubMessageHandler pubSubMessageHandler(PubSubTemplate pubSubTemplate)
// end::message_router[]
// tag::adapter_callback[]
- adapter.setPublishCallback(
- new ListenableFutureCallback() {
- @Override
- public void onFailure(Throwable ex) {}
-
- @Override
- public void onSuccess(String result) {}
- });
+ adapter.setSuccessCallback((ackId, message) -> {});
+ adapter.setFailureCallback((cause, message) -> {});
// end::adapter_callback[]
return adapter;
@@ -421,7 +413,7 @@ void run(
throws ExecutionException, InterruptedException;
}
- class Logger {
+ static class Logger {
List messages = new ArrayList<>();
void info(String message) {
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubTemplateIntegrationTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubTemplateIntegrationTests.java
index 141ce1c784..91cf6d73db 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubTemplateIntegrationTests.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/pubsub/it/PubSubTemplateIntegrationTests.java
@@ -50,7 +50,6 @@
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.awaitility.Awaitility;
@@ -181,10 +180,10 @@ void testPullAndAck() {
messagesSet.addAll(
newMessages.stream()
.map(message -> message.getPubsubMessage().getData().toStringUtf8())
- .collect(Collectors.toList()));
+ .toList());
}
- assertThat(messagesSet.size()).as("check that we received all the messages").isEqualTo(3);
+ assertThat(messagesSet).as("check that we received all the messages").hasSize(3);
ackableMessages.forEach(
message -> {
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/secretmanager/SecretManagerBootstrapConfigurationTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/secretmanager/SecretManagerBootstrapConfigurationTests.java
deleted file mode 100644
index bebf08db07..0000000000
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/secretmanager/SecretManagerBootstrapConfigurationTests.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright 2020-2020 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.cloud.spring.autoconfigure.secretmanager;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import com.google.api.gax.core.CredentialsProvider;
-import com.google.api.gax.rpc.NotFoundException;
-import com.google.auth.Credentials;
-import com.google.cloud.secretmanager.v1.AccessSecretVersionResponse;
-import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
-import com.google.cloud.secretmanager.v1.SecretPayload;
-import com.google.cloud.secretmanager.v1.SecretVersionName;
-import com.google.protobuf.ByteString;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.WebApplicationType;
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
-import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/** Unit tests for {@link GcpSecretManagerBootstrapConfiguration}. */
-class SecretManagerBootstrapConfigurationTests {
-
- private static final String PROJECT_NAME = "hollow-light-of-the-sealed-land";
-
- private SpringApplicationBuilder applicationBuilder =
- new SpringApplicationBuilder(
- TestBootstrapConfiguration.class, GcpSecretManagerBootstrapConfiguration.class)
- .properties(
- "spring.cloud.gcp.secretmanager.project-id=" + PROJECT_NAME,
- "spring.cloud.bootstrap.enabled=true",
- "spring.cloud.gcp.sql.enabled=false")
- .web(WebApplicationType.NONE);
-
- @Test
- void testGetProperty() {
- try (ConfigurableApplicationContext c = applicationBuilder.run()) {
- String secret = c.getEnvironment().getProperty("sm://my-secret");
- assertThat(secret).isEqualTo("hello");
- }
- }
-
- @Test
- void testGetProperty_otherVersion() {
- try (ConfigurableApplicationContext c = applicationBuilder.run()) {
- String secret = c.getEnvironment().getProperty("sm://my-secret/1");
- assertThat(secret).isEqualTo("hello v1");
- }
- }
-
- @Test
- void testGetProperty_otherProject() {
- try (ConfigurableApplicationContext c = applicationBuilder.run()) {
- String secret =
- c.getEnvironment()
- .getProperty("sm://projects/other-project/secrets/other-secret/versions/3");
- assertThat(secret).isEqualTo("goodbye");
- }
- }
-
- @Test
- void testValueAnnotation() {
- try (ConfigurableApplicationContext c = applicationBuilder.run()) {
- String secret = c.getBean("secret", String.class);
- assertThat(secret).isEqualTo("hello");
-
- secret = c.getBean("fullyQualifiedSecret", String.class);
- assertThat(secret).isEqualTo("hello");
- }
- }
-
- @Test
- void configurationDisabled() {
- SpringApplicationBuilder disabledConfigurationApp =
- new SpringApplicationBuilder(
- TestBootstrapConfiguration.class, GcpSecretManagerBootstrapConfiguration.class)
- .properties("spring.cloud.gcp.secretmanager.project-id=" + PROJECT_NAME)
- .properties("spring.cloud.gcp.secretmanager.enabled=false")
- .properties("spring.cloud.gcp.sql.enabled=false")
- .web(WebApplicationType.NONE);
-
- try (ConfigurableApplicationContext c = disabledConfigurationApp.run()) {
- String secret = c.getEnvironment().getProperty("sm://my-secret");
- assertThat(secret).isNull();
- }
- }
-
- @Configuration
- static class TestBootstrapConfiguration {
-
- @Value("${sm://my-secret}")
- private String secret;
-
- @Value("${sm://" + PROJECT_NAME + "/my-secret/latest}")
- private String fullyQualifiedSecret;
-
- @Bean
- public String secret() {
- return secret;
- }
-
- @Bean
- public String fullyQualifiedSecret() {
- return secret;
- }
-
- @Bean
- public static SecretManagerServiceClient secretManagerClient() {
- SecretManagerServiceClient client = mock(SecretManagerServiceClient.class);
-
- SecretVersionName secretVersionName =
- SecretVersionName.newBuilder()
- .setProject(PROJECT_NAME)
- .setSecret("my-secret")
- .setSecretVersion("latest")
- .build();
-
- when(client.accessSecretVersion(secretVersionName))
- .thenReturn(
- AccessSecretVersionResponse.newBuilder()
- .setPayload(SecretPayload.newBuilder().setData(ByteString.copyFromUtf8("hello")))
- .build());
-
- secretVersionName =
- SecretVersionName.newBuilder()
- .setProject(PROJECT_NAME)
- .setSecret("fake-secret")
- .setSecretVersion("latest")
- .build();
-
- when(client.accessSecretVersion(secretVersionName))
- .thenThrow(NotFoundException.class);
-
- secretVersionName =
- SecretVersionName.newBuilder()
- .setProject(PROJECT_NAME)
- .setSecret("my-secret")
- .setSecretVersion("1")
- .build();
-
- when(client.accessSecretVersion(secretVersionName))
- .thenReturn(
- AccessSecretVersionResponse.newBuilder()
- .setPayload(
- SecretPayload.newBuilder().setData(ByteString.copyFromUtf8("hello v1")))
- .build());
-
- secretVersionName =
- SecretVersionName.newBuilder()
- .setProject("other-project")
- .setSecret("other-secret")
- .setSecretVersion("3")
- .build();
-
- when(client.accessSecretVersion(secretVersionName))
- .thenReturn(
- AccessSecretVersionResponse.newBuilder()
- .setPayload(
- SecretPayload.newBuilder().setData(ByteString.copyFromUtf8("goodbye")))
- .build());
-
- return client;
- }
-
- @Bean
- public static CredentialsProvider googleCredentials() {
- return () -> mock(Credentials.class);
- }
-
- // This is added in here to verify that the Secret Manager property source locator bean
- // still gets created even if another PropertySourceLocator bean exists in the environment.
- @Bean
- public static PropertySourceLocator defaultPropertySourceLocator() {
- return locatorEnvironment -> null;
- }
- }
-}
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/secretmanager/SecretManagerCompatibilityTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/secretmanager/SecretManagerCompatibilityTests.java
index b5aaa3748c..bd807f5600 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/secretmanager/SecretManagerCompatibilityTests.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/secretmanager/SecretManagerCompatibilityTests.java
@@ -10,8 +10,6 @@
import com.google.cloud.secretmanager.v1.SecretManagerServiceClient;
import com.google.cloud.secretmanager.v1.SecretPayload;
import com.google.cloud.secretmanager.v1.SecretVersionName;
-import com.google.cloud.spring.autoconfigure.secretmanager.SecretManagerBootstrapConfigurationTests.TestBootstrapConfiguration;
-import com.google.cloud.spring.secretmanager.SecretManagerTemplate;
import com.google.protobuf.ByteString;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -32,7 +30,7 @@ class SecretManagerCompatibilityTests {
@BeforeEach
void init() {
- application = new SpringApplicationBuilder(GcpSecretManagerBootstrapConfiguration.class)
+ application = new SpringApplicationBuilder(SecretManagerCompatibilityTests.class)
.web(WebApplicationType.NONE)
.properties(
"spring.cloud.gcp.secretmanager.project-id=" + PROJECT_NAME,
@@ -61,44 +59,14 @@ void init() {
.thenThrow(NotFoundException.class);
}
- /**
- * Users with the legacy configuration (i.e., bootstrap phrase) should get {@link
- * SecretManagerTemplate} autoconfiguration and properties resolved. Note that {@link
- * TestBootstrapConfiguration} is automatically picked to create a mock {@link
- * SecretManagerServiceClient} object as it is specified in spring.factories.
- */
- @Test
- void testLegacyConfigurationWhenDefaultSecretIsNotAllowed() {
- application.properties("spring.cloud.bootstrap.enabled=true");
- try (ConfigurableApplicationContext applicationContext = application.run()) {
- ConfigurableEnvironment environment = applicationContext.getEnvironment();
- assertThat(environment.getProperty("sm://my-secret")).isEqualTo("hello");
- assertThatThrownBy(() -> environment.getProperty("sm://fake-secret"))
- .isExactlyInstanceOf(NotFoundException.class);
- }
- }
-
- @Test
- void testLegacyConfigurationWhenDefaultSecretIsAllowed() {
- application.properties(
- "spring.cloud.bootstrap.enabled=true",
- "spring.cloud.gcp.secretmanager.allow-default-secret=true");
- try (ConfigurableApplicationContext applicationContext = application.run()) {
- ConfigurableEnvironment environment = applicationContext.getEnvironment();
- assertThat(environment.getProperty("sm://my-secret")).isEqualTo("hello");
- assertThat(environment.getProperty("sm://fake-secret")).isNull();
- }
- }
-
/**
* Users with the new configuration (i.e., using `spring.config.import`) should get {@link
* com.google.cloud.spring.secretmanager.SecretManagerTemplate} autoconfiguration and properties
* resolved.
*/
@Test
- void testNewConfigurationWhenDefaultSecretIsNotAllowed() {
+ void testConfigurationWhenDefaultSecretIsNotAllowed() {
application.properties(
- "spring.cloud.gcp.secretmanager.legacy=false",
"spring.config.import=sm://")
.addBootstrapRegistryInitializer(
(registry) -> registry.registerIfAbsent(
@@ -115,9 +83,8 @@ void testNewConfigurationWhenDefaultSecretIsNotAllowed() {
}
@Test
- void testNewConfigurationWhenDefaultSecretIsAllowed() {
+ void testConfigurationWhenDefaultSecretIsAllowed() {
application.properties(
- "spring.cloud.gcp.secretmanager.legacy=false",
"spring.cloud.gcp.secretmanager.allow-default-secret=true",
"spring.config.import=sm://")
.addBootstrapRegistryInitializer(
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/security/IapAuthenticationAutoConfigurationTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/security/IapAuthenticationAutoConfigurationTests.java
index 75b33965b5..511e30df4a 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/security/IapAuthenticationAutoConfigurationTests.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/security/IapAuthenticationAutoConfigurationTests.java
@@ -29,9 +29,9 @@
import com.google.cloud.spring.security.iap.AppEngineAudienceProvider;
import com.google.cloud.spring.security.iap.AudienceProvider;
import com.google.cloud.spring.security.iap.AudienceValidator;
+import jakarta.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.util.Collections;
-import javax.servlet.http.HttpServletRequest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/spanner/TestRepository.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/spanner/TestRepository.java
index 8666f59f15..47ee3929d2 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/spanner/TestRepository.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/spanner/TestRepository.java
@@ -21,4 +21,4 @@
/** A repository for testing instantiation. */
@Repository
-public interface TestRepository extends SpannerRepository {}
+public interface TestRepository extends SpannerRepository {}
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/sql/R2dbcCloudSqlEnvironmentPostProcessorTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/sql/R2dbcCloudSqlEnvironmentPostProcessorTests.java
index 44a34dbd76..288496f5d7 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/sql/R2dbcCloudSqlEnvironmentPostProcessorTests.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/sql/R2dbcCloudSqlEnvironmentPostProcessorTests.java
@@ -20,6 +20,7 @@
import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringApplication;
@@ -29,7 +30,7 @@
/** Tests for {@link R2dbcCloudSqlEnvironmentPostProcessor}. */
class R2dbcCloudSqlEnvironmentPostProcessorTests {
- private R2dbcCloudSqlEnvironmentPostProcessor r2dbcPostProcessor =
+ private final R2dbcCloudSqlEnvironmentPostProcessor r2dbcPostProcessor =
new R2dbcCloudSqlEnvironmentPostProcessor();
ApplicationContextRunner contextRunner =
@@ -39,15 +40,6 @@ class R2dbcCloudSqlEnvironmentPostProcessorTests {
r2dbcPostProcessor.postProcessEnvironment(
configurableApplicationContext.getEnvironment(), new SpringApplication()));
- @Test
- void testCreateUrl_mySql() {
- GcpCloudSqlProperties properties = new GcpCloudSqlProperties();
- properties.setDatabaseName("my-database");
- properties.setInstanceConnectionName("my-instance-connection-name");
- String r2dbcUrl = r2dbcPostProcessor.createUrl(DatabaseType.MYSQL, properties);
- assertThat(r2dbcUrl).isEqualTo("r2dbc:gcp:mysql://my-instance-connection-name/my-database");
- }
-
@Test
void testCreateUrl_postgres() {
GcpCloudSqlProperties properties = new GcpCloudSqlProperties();
@@ -57,65 +49,14 @@ void testCreateUrl_postgres() {
assertThat(r2dbcUrl).isEqualTo("r2dbc:gcp:postgres://my-instance-connection-name/my-database");
}
- @Test
- void testSetR2dbcProperty_mySql_defaultUsername() {
- this.contextRunner
- .withPropertyValues(
- "spring.cloud.gcp.sql.databaseName=my-database",
- "spring.cloud.gcp.sql.instanceConnectionName=my-project:region:my-instance")
- .run(
- context -> {
- assertThat(context.getEnvironment().getProperty("spring.r2dbc.url"))
- .isEqualTo("r2dbc:gcp:mysql://my-project:region:my-instance/my-database");
- assertThat(context.getEnvironment().getProperty("spring.r2dbc.username"))
- .isEqualTo("root");
- });
- }
-
- @Test
- void testSetR2dbcProperty_mySql_usernameProvided() {
- this.contextRunner
- .withPropertyValues(
- "spring.cloud.gcp.sql.databaseName=my-database",
- "spring.cloud.gcp.sql.instanceConnectionName=my-project:region:my-instance",
- "spring.r2dbc.username=my-username")
- .run(
- context -> {
- assertThat(context.getEnvironment().getProperty("spring.r2dbc.url"))
- .isEqualTo("r2dbc:gcp:mysql://my-project:region:my-instance/my-database");
- assertThat(context.getEnvironment().getProperty("spring.r2dbc.username"))
- .isEqualTo("my-username");
- });
- }
-
- @Test
- void testSetR2dbcProperty_mySql_urlProvidedByUserIgnored() {
- this.contextRunner
- .withPropertyValues(
- "spring.cloud.gcp.sql.databaseName=my-database",
- "spring.cloud.gcp.sql.instanceConnectionName=my-project:region:my-instance",
- "spring.r2dbc.url=ignored")
- .run(
- context -> {
- assertThat(context.getEnvironment().getProperty("spring.r2dbc.url"))
- .isEqualTo("r2dbc:gcp:mysql://my-project:region:my-instance/my-database");
- });
- }
-
@Test
void testSetR2dbcProperty_postgres() {
- verifyThatCorrectUrlAndUsernameSet(new String[] {"io.r2dbc.postgresql"},
+ verifyThatCorrectUrlAndUsernameSet(
+ new String[] {"io.r2dbc.postgresql"},
"postgres",
"r2dbc:gcp:postgres://my-project:region:my-instance/my-database");
}
- @Test
- void testSetR2dbcProperty_mysql() {
- verifyThatCorrectUrlAndUsernameSet(new String[] {"dev.miku.r2dbc.mysql"},
- "root",
- "r2dbc:gcp:mysql://my-project:region:my-instance/my-database");
- }
-
/**
* Verifies that correct database properties got injected into context, given a passed-in list of
* packages to retain on the classpath.
@@ -125,14 +66,13 @@ void testSetR2dbcProperty_mysql() {
* @param url expected {@code spring.r2dbc.username} value to verify
*/
private void verifyThatCorrectUrlAndUsernameSet(
- String[] driverPackagesToInclude, String username, String url) {
+ String[] driverPackagesToInclude,
+ String username,
+ String url) {
// Because `FilteredClassLoader` accepts a list of packages to remove from classpath,
// `driverPackagesToInclude` is used to calculate the inverse list of packages to _exclude_.
- Set driverPackagesToExclude = new HashSet<>(Arrays.asList(
- "dev.miku.r2dbc.mysql",
- "io.r2dbc.postgresql"
- ));
- driverPackagesToExclude.removeAll(Arrays.asList(driverPackagesToInclude));
+ Set driverPackagesToExclude = new HashSet<>(List.of("io.r2dbc.postgresql"));
+ Arrays.asList(driverPackagesToInclude).forEach(driverPackagesToExclude::remove);
this.contextRunner
.withPropertyValues(
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/trace/StackdriverTraceAutoConfigurationTests.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/trace/StackdriverTraceAutoConfigurationTests.java
index 7abf8c6ccf..f18b93949a 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/trace/StackdriverTraceAutoConfigurationTests.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/trace/StackdriverTraceAutoConfigurationTests.java
@@ -23,12 +23,14 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import brave.Tracer;
import brave.TracingCustomizer;
import brave.handler.SpanHandler;
-import brave.http.HttpRequestParser;
-import brave.http.HttpTracingCustomizer;
+import brave.propagation.TraceContextOrSamplingFlags;
import com.google.api.gax.core.ExecutorProvider;
import com.google.cloud.spring.autoconfigure.core.GcpContextAutoConfiguration;
+import com.google.cloud.spring.autoconfigure.trace.StackdriverTraceAutoConfigurationTests.MultipleSpanHandlersConfig.GcpTraceService;
+import com.google.cloud.spring.autoconfigure.trace.StackdriverTraceAutoConfigurationTests.MultipleSpanHandlersConfig.OtherSender;
import com.google.devtools.cloudtrace.v2.BatchWriteSpansRequest;
import com.google.devtools.cloudtrace.v2.Span;
import com.google.devtools.cloudtrace.v2.TraceServiceGrpc;
@@ -47,12 +49,12 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.reflect.FieldUtils;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.boot.actuate.autoconfigure.tracing.BraveAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
-import org.springframework.cloud.sleuth.Tracer;
-import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import zipkin2.Call;
@@ -67,17 +69,21 @@
/** Tests for auto-config. */
class StackdriverTraceAutoConfigurationTests {
- private ApplicationContextRunner contextRunner =
- new ApplicationContextRunner()
- .withConfiguration(
- AutoConfigurations.of(
- StackdriverTraceAutoConfiguration.class,
- GcpContextAutoConfiguration.class,
- BraveAutoConfiguration.class,
- RefreshAutoConfiguration.class))
- .withUserConfiguration(MockConfiguration.class)
- .withPropertyValues(
- "spring.cloud.gcp.project-id=proj", "spring.sleuth.sampler.probability=1.0");
+ private ApplicationContextRunner contextRunner;
+
+ @BeforeEach
+ void init() {
+ contextRunner = new ApplicationContextRunner()
+ .withConfiguration(
+ AutoConfigurations.of(
+ StackdriverTraceAutoConfiguration.class,
+ GcpContextAutoConfiguration.class,
+ BraveAutoConfiguration.class,
+ RefreshAutoConfiguration.class))
+ .withUserConfiguration(MockConfiguration.class)
+ .withPropertyValues(
+ "spring.cloud.gcp.project-id=proj");
+ }
@Test
void test() {
@@ -88,8 +94,6 @@ void test() {
() -> SpanHandler.NOOP)
.run(
context -> {
- assertThat(context.getBean(HttpRequestParser.class)).isNotNull();
- assertThat(context.getBean(HttpTracingCustomizer.class)).isNotNull();
assertThat(
context.getBean(
StackdriverTraceAutoConfiguration.SENDER_BEAN_NAME, Sender.class))
@@ -165,8 +169,6 @@ void supportsMultipleReporters() {
.withUserConfiguration(MultipleSpanHandlersConfig.class)
.run(
context -> {
- assertThat(context.getBean(HttpRequestParser.class)).isNotNull();
- assertThat(context.getBean(HttpTracingCustomizer.class)).isNotNull();
assertThat(context.getBean(ManagedChannel.class)).isNotNull();
assertThat(context.getBeansOfType(Sender.class)).hasSize(2);
assertThat(context.getBeansOfType(Sender.class))
@@ -174,13 +176,18 @@ void supportsMultipleReporters() {
assertThat(context.getBeansOfType(SpanHandler.class))
.containsKeys("stackdriverSpanHandler", "otherSpanHandler");
- org.springframework.cloud.sleuth.Span span =
- context.getBean(Tracer.class).nextSpan().name("foo").tag("foo", "bar").start();
- span.end();
- String spanId = span.context().spanId();
+ brave.Span span = context
+ .getBean(Tracer.class)
+ // always send the trace
+ .nextSpan(TraceContextOrSamplingFlags.SAMPLED)
+ .name("foo")
+ .tag("foo", "bar")
+ .start();
+ span.finish();
+ String spanId = span.context().spanIdString();
+ GcpTraceService gcpTraceService =
+ context.getBean(GcpTraceService.class);
- MultipleSpanHandlersConfig.GcpTraceService gcpTraceService =
- context.getBean(MultipleSpanHandlersConfig.GcpTraceService.class);
await()
.atMost(10, TimeUnit.SECONDS)
.pollInterval(Duration.ofSeconds(1))
@@ -202,8 +209,8 @@ void supportsMultipleReporters() {
.isEqualTo("bar");
});
- MultipleSpanHandlersConfig.OtherSender sender =
- (MultipleSpanHandlersConfig.OtherSender) context.getBean("otherSender");
+ OtherSender sender =
+ (OtherSender) context.getBean("otherSender");
await()
.atMost(10, TimeUnit.SECONDS)
.untilAsserted(() -> assertThat(sender.isSpanSent()).isTrue());
@@ -299,9 +306,8 @@ TracingCustomizer otherTracingCustomizer(SpanHandler otherSpanHandler) {
@Bean
SpanHandler otherSpanHandler(OtherSender otherSender) {
- AsyncReporter reporter = AsyncReporter.create(otherSender);
- SpanHandler spanHandler = AsyncZipkinSpanHandler.create(reporter);
- return spanHandler;
+ AsyncReporter reporter = AsyncReporter.create(otherSender);
+ return AsyncZipkinSpanHandler.create(reporter);
}
@Bean
@@ -343,7 +349,7 @@ public Call sendSpans(List encodedSpans) {
/** Used as implementation on the in-process gRPC server for verification. */
static class GcpTraceService extends TraceServiceGrpc.TraceServiceImplBase {
- private Map traces = new HashMap<>();
+ private final Map traces = new HashMap<>();
boolean hasSpan(String spanId) {
return this.traces.containsKey(spanId);
diff --git a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/trace/pubsub/TracePubSubAutoConfigurationTest.java b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/trace/pubsub/TracePubSubAutoConfigurationTest.java
index 8955eac4e2..a09079cb77 100644
--- a/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/trace/pubsub/TracePubSubAutoConfigurationTest.java
+++ b/spring-cloud-gcp-autoconfigure/src/test/java/com/google/cloud/spring/autoconfigure/trace/pubsub/TracePubSubAutoConfigurationTest.java
@@ -23,9 +23,9 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import brave.Tracing;
import brave.handler.SpanHandler;
-import brave.http.HttpRequestParser;
-import brave.http.HttpTracingCustomizer;
+import brave.messaging.MessagingTracing;
import com.google.api.core.ApiFunction;
import com.google.cloud.pubsub.v1.Publisher;
import com.google.cloud.spring.autoconfigure.core.GcpContextAutoConfiguration;
@@ -33,47 +33,50 @@
import com.google.cloud.spring.autoconfigure.trace.StackdriverTraceAutoConfiguration;
import com.google.cloud.spring.pubsub.core.publisher.PublisherCustomizer;
import io.grpc.ManagedChannel;
+import io.micrometer.observation.aop.ObservedAspect;
import java.util.List;
import java.util.stream.Collectors;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
-import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
-import org.springframework.cloud.sleuth.autoconfig.brave.instrument.messaging.BraveMessagingAutoConfiguration;
import zipkin2.reporter.Reporter;
import zipkin2.reporter.Sender;
/** Tests for Trace Pub/Sub auto-config. */
class TracePubSubAutoConfigurationTest {
- private ApplicationContextRunner contextRunner =
- new ApplicationContextRunner()
- .withConfiguration(
- AutoConfigurations.of(
- TracePubSubAutoConfiguration.class,
- StackdriverTraceAutoConfiguration.class,
- GcpContextAutoConfiguration.class,
- BraveAutoConfiguration.class,
- BraveMessagingAutoConfiguration.class,
- RefreshAutoConfiguration.class))
- .withUserConfiguration(MockConfiguration.class)
- .withBean(
- StackdriverTraceAutoConfiguration.SPAN_HANDLER_BEAN_NAME,
- SpanHandler.class,
- () -> SpanHandler.NOOP)
- // Prevent healthcheck from triggering a real call to Trace.
- .withBean(REPORTER_BEAN_NAME, Reporter.class, () -> mock(Reporter.class))
- .withPropertyValues(
- "spring.cloud.gcp.project-id=proj", "spring.sleuth.sampler.probability=1.0");
+ private ApplicationContextRunner contextRunner;
+
+ @BeforeEach
+ void init() {
+ contextRunner =
+ new ApplicationContextRunner()
+ .withConfiguration(
+ AutoConfigurations.of(
+ TracePubSubAutoConfiguration.class,
+ StackdriverTraceAutoConfiguration.class,
+ GcpContextAutoConfiguration.class,
+ RefreshAutoConfiguration.class,
+ ObservationAutoConfiguration.class))
+ .withUserConfiguration(MockConfiguration.class)
+ .withBean(
+ StackdriverTraceAutoConfiguration.SPAN_HANDLER_BEAN_NAME,
+ SpanHandler.class,
+ () -> SpanHandler.NOOP)
+ // Prevent health-check from triggering a real call to Trace.
+ .withBean(REPORTER_BEAN_NAME, Reporter.class, () -> mock(Reporter.class))
+ .withPropertyValues(
+ "spring.cloud.gcp.project-id=proj");
+ }
@Test
void test() {
this.contextRunner.run(
context -> {
- assertThat(context.getBean(HttpRequestParser.class)).isNotNull();
- assertThat(context.getBean(HttpTracingCustomizer.class)).isNotNull();
assertThat(
context.getBean(StackdriverTraceAutoConfiguration.SENDER_BEAN_NAME, Sender.class))
.isNotNull();
@@ -87,25 +90,34 @@ void testPubSubTracingDisabledByDefault() {
context -> {
assertThat(context.getBeansOfType(TracePubSubBeanPostProcessor.class)).isEmpty();
assertThat(context.getBeansOfType(PubSubTracing.class)).isEmpty();
+ assertThat(context.getBeansOfType(MessagingTracing.class)).isEmpty();
+ assertThat(context.getBeansOfType(ObservedAspect.class)).isEmpty();
});
}
@Test
void testPubSubTracingEnabled() {
+ Tracing tracing = Tracing.newBuilder().build();
this.contextRunner
.withPropertyValues("spring.cloud.gcp.trace.pubsub.enabled=true")
+ .withBean(Tracing.class, () -> tracing)
.run(
context -> {
assertThat(context.getBean(TracePubSubBeanPostProcessor.class)).isNotNull();
assertThat(context.getBean(PubSubTracing.class)).isNotNull();
+ assertThat(context.getBean(MessagingTracing.class)).isNotNull();
+ assertThat(context.getBean(ObservedAspect.class)).isNotNull();
});
}
@Test
void tracePubSubCustomizerAppliedLast() {
PublisherCustomizer noopCustomizer = (pb, t) -> {};
+ Tracing tracing = Tracing.newBuilder().build();
this.contextRunner
.withPropertyValues("spring.cloud.gcp.trace.pubsub.enabled=true")
+ .withBean(Tracing.class, () -> tracing)
+ .withBean(MessagingTracing.class, () -> MessagingTracing.newBuilder(tracing).build())
.withBean(PublisherCustomizer.class, () -> noopCustomizer)
.run(context -> {
ObjectProvider customizersProvider =
@@ -114,7 +126,7 @@ void tracePubSubCustomizerAppliedLast() {
customizersProvider.orderedStream().collect(Collectors.toList());
assertThat(customizers).hasSize(2);
- // Object provider lists highest priority first, so default priority `noopCustomizer`
+ // Object provider lists the highest priority first, so default priority `noopCustomizer`
// will be second
assertThat(customizers.get(1)).isSameAs(noopCustomizer);
diff --git a/spring-cloud-gcp-bigquery/pom.xml b/spring-cloud-gcp-bigquery/pom.xml
index a779228b02..51eea2797c 100644
--- a/spring-cloud-gcp-bigquery/pom.xml
+++ b/spring-cloud-gcp-bigquery/pom.xml
@@ -7,7 +7,7 @@
spring-cloud-gcp
com.google.cloud
- 3.4.3-SNAPSHOT
+ 4.0.0-SNAPSHOT
spring-cloud-gcp-bigquery
diff --git a/spring-cloud-gcp-bigquery/src/main/java/com/google/cloud/spring/bigquery/core/BigQueryOperations.java b/spring-cloud-gcp-bigquery/src/main/java/com/google/cloud/spring/bigquery/core/BigQueryOperations.java
index 2ec50410d8..5b1c1d7af9 100644
--- a/spring-cloud-gcp-bigquery/src/main/java/com/google/cloud/spring/bigquery/core/BigQueryOperations.java
+++ b/spring-cloud-gcp-bigquery/src/main/java/com/google/cloud/spring/bigquery/core/BigQueryOperations.java
@@ -20,7 +20,7 @@
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.Schema;
import java.io.InputStream;
-import org.springframework.util.concurrent.ListenableFuture;
+import java.util.concurrent.CompletableFuture;
/**
* Defines operations for use with BigQuery.
@@ -35,10 +35,10 @@ public interface BigQueryOperations {
* @param tableName name of the table to write to
* @param inputStream input stream of the table data to write
* @param dataFormatOptions the format of the data to write
- * @return {@link ListenableFuture} containing the BigQuery Job indicating completion of operation
+ * @return {@link CompletableFuture} containing the BigQuery Job indicating completion of operation
* @throws BigQueryException if errors occur when loading data to the BigQuery table
*/
- ListenableFuture writeDataToTable(
+ CompletableFuture writeDataToTable(
String tableName, InputStream inputStream, FormatOptions dataFormatOptions);
/**
@@ -53,7 +53,7 @@ ListenableFuture writeDataToTable(
* Field.of("County", StandardSQLTypeName.STRING)
* );
*
- * ListenableFuture bigQueryJobFuture =
+ * CompletableFuture bigQueryJobFuture =
* bigQueryTemplate.writeDataToTable(
* TABLE_NAME, dataFile.getInputStream(), FormatOptions.csv(), schema);
* }
@@ -62,10 +62,10 @@ ListenableFuture writeDataToTable(
* @param inputStream input stream of the table data to write
* @param dataFormatOptions the format of the data to write
* @param schema the schema of the table being loaded
- * @return {@link ListenableFuture} containing the BigQuery Job indicating completion of operation
+ * @return {@link CompletableFuture} containing the BigQuery Job indicating completion of operation
* @throws BigQueryException if errors occur when loading data to the BigQuery table
*/
- ListenableFuture writeDataToTable(
+ CompletableFuture writeDataToTable(
String tableName, InputStream inputStream, FormatOptions dataFormatOptions, Schema schema);
/**
@@ -75,10 +75,10 @@ ListenableFuture writeDataToTable(
*
* @param tableName name of the table to write to
* @param jsonInputStream input stream of the json file to be written
- * @return {@link ListenableFuture} containing the WriteApiResponse indicating completion of
+ * @return {@link CompletableFuture} containing the WriteApiResponse indicating completion of
* operation
*/
- ListenableFuture writeJsonStream(String tableName, InputStream jsonInputStream);
+ CompletableFuture writeJsonStream(String tableName, InputStream jsonInputStream);
/**
* This method uses BigQuery Storage Write API to write new line delimited JSON file to the
@@ -86,9 +86,9 @@ ListenableFuture writeDataToTable(
*
* @param tableName name of the table to write to
* @param jsonInputStream input stream of the json file to be written
- * @return {@link ListenableFuture} containing the WriteApiResponse indicating completion of
+ * @return {@link CompletableFuture} containing the WriteApiResponse indicating completion of
* operation
*/
- ListenableFuture writeJsonStream(
+ CompletableFuture writeJsonStream(
String tableName, InputStream jsonInputStream, Schema schema);
}
diff --git a/spring-cloud-gcp-bigquery/src/main/java/com/google/cloud/spring/bigquery/core/BigQueryTemplate.java b/spring-cloud-gcp-bigquery/src/main/java/com/google/cloud/spring/bigquery/core/BigQueryTemplate.java
index d8fb8dc681..fe685ba460 100644
--- a/spring-cloud-gcp-bigquery/src/main/java/com/google/cloud/spring/bigquery/core/BigQueryTemplate.java
+++ b/spring-cloud-gcp-bigquery/src/main/java/com/google/cloud/spring/bigquery/core/BigQueryTemplate.java
@@ -45,17 +45,15 @@
import java.nio.channels.Channels;
import java.time.Duration;
import java.util.Map;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledFuture;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.TaskScheduler;
-import org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
-import org.springframework.util.concurrent.ListenableFuture;
-import org.springframework.util.concurrent.SettableListenableFuture;
/**
* Helper class which simplifies common operations done in BigQuery.
@@ -87,43 +85,7 @@ public class BigQueryTemplate implements BigQueryOperations {
private final Logger logger = LoggerFactory.getLogger(BigQueryTemplate.class);
- private int jsonWriterBatchSize;
-
- /**
- * Creates the {@link BigQuery} template.
- *
- * @param bigQuery the underlying client object used to interface with BigQuery
- * @param datasetName the name of the dataset in which all operations will take place
- * @deprecated As of release 3.3.1, use
- * BigQueryTemplate(BigQuery,BigQueryWriteClient,Map,TaskScheduler) instead
- */
- @Deprecated
- public BigQueryTemplate(BigQuery bigQuery, String datasetName) {
- this(bigQuery, datasetName, new DefaultManagedTaskScheduler());
- }
-
- /**
- * Creates the {@link BigQuery} template.
- *
- * @param bigQuery the underlying client object used to interface with BigQuery
- * @param datasetName the name of the dataset in which all operations will take place
- * @param taskScheduler the {@link TaskScheduler} used to poll for the status of long-running
- * BigQuery operations
- * @deprecated As of release 3.3.1, use
- * BigQueryTemplate(BigQuery,BigQueryWriteClient,Map,TaskScheduler) instead
- */
- @Deprecated
- public BigQueryTemplate(BigQuery bigQuery, String datasetName, TaskScheduler taskScheduler) {
- Assert.notNull(bigQuery, "BigQuery client object must not be null.");
- Assert.notNull(datasetName, "Dataset name must not be null");
- Assert.notNull(taskScheduler, "TaskScheduler must not be null");
-
- this.bigQuery = bigQuery;
- this.datasetName = datasetName;
- this.taskScheduler = taskScheduler;
- this.bigQueryWriteClient =
- null; // This constructor is Deprecated. We cannot use BigQueryWriteClient with this
- }
+ private final int jsonWriterBatchSize;
/**
* A Full constructor which creates the {@link BigQuery} template.
@@ -203,13 +165,13 @@ public void setJobPollInterval(Duration jobPollInterval) {
}
@Override
- public ListenableFuture writeDataToTable(
+ public CompletableFuture writeDataToTable(
String tableName, InputStream inputStream, FormatOptions dataFormatOptions) {
return this.writeDataToTable(tableName, inputStream, dataFormatOptions, null);
}
@Override
- public ListenableFuture writeDataToTable(
+ public CompletableFuture writeDataToTable(
String tableName, InputStream inputStream, FormatOptions dataFormatOptions, Schema schema) {
TableId tableId = TableId.of(datasetName, tableName);
@@ -247,11 +209,11 @@ public ListenableFuture writeDataToTable(
*
* @param tableName name of the table to write to
* @param jsonInputStream input stream of the json file to be written
- * @return {@link ListenableFuture} containing the WriteApiResponse indicating completion of
+ * @return {@link CompletableFuture} containing the WriteApiResponse indicating completion of
* operation
*/
@Override
- public ListenableFuture writeJsonStream(
+ public CompletableFuture writeJsonStream(
String tableName, InputStream jsonInputStream, Schema schema) {
createTable(tableName, schema); // create table if it's not already created
return writeJsonStream(tableName, jsonInputStream);
@@ -278,32 +240,29 @@ public Table createTable(
*
* @param tableName name of the table to write to
* @param jsonInputStream input stream of the json file to be written
- * @return {@link ListenableFuture} containing the WriteApiResponse indicating completion of
+ * @return {@link CompletableFuture} containing the WriteApiResponse indicating completion of
* operation
*/
@Override
- public ListenableFuture writeJsonStream(
+ public CompletableFuture writeJsonStream(
String tableName, InputStream jsonInputStream) {
- SettableListenableFuture writeApiFutureResponse =
- new SettableListenableFuture<>();
+ CompletableFuture writeApiFutureResponse =
+ new CompletableFuture<>();
Thread asyncTask =
new Thread(
() -> {
try {
WriteApiResponse apiResponse = getWriteApiResponse(tableName, jsonInputStream);
- writeApiFutureResponse.set(apiResponse);
+ writeApiFutureResponse.complete(apiResponse);
} catch (DescriptorValidationException | IOException e) {
- writeApiFutureResponse.setException(e);
+ writeApiFutureResponse.completeExceptionally(e);
logger.warn(String.format("Error: %s %n", e.getMessage()), e);
- } catch (InterruptedException e) {
- writeApiFutureResponse.setException(e);
+ } catch (Exception e) {
+ writeApiFutureResponse.completeExceptionally(e);
// Restore interrupted state in case of an InterruptedException
Thread.currentThread().interrupt();
- } catch (Throwable t) {
- writeApiFutureResponse.setException(t);
- Thread.currentThread().interrupt();
}
});
asyncTask
@@ -311,13 +270,16 @@ public ListenableFuture writeJsonStream(
// thread can be run in the ExecutorService when it has been wired-in
// register success and failure callback
- writeApiFutureResponse.addCallback(
- res -> logger.info("Data successfully written"),
- res -> {
- asyncTask.interrupt(); // interrupt the thread as the developer might have cancelled the
- // Future.
- // This can be replaced with interrupting the ExecutorService when it has been wired-in
- logger.info("asyncTask interrupted");
+ writeApiFutureResponse.whenComplete(
+ (writeApiResponse, exception) -> {
+ if (exception != null) {
+ asyncTask.interrupt(); // interrupt the thread as the developer might have cancelled the
+ // Future.
+ // This can be replaced with interrupting the ExecutorService when it has been wired-in
+ logger.info("asyncTask interrupted");
+ return;
+ }
+ logger.info("Data successfully written");
});
return writeApiFutureResponse;
@@ -370,7 +332,7 @@ public WriteApiResponse getWriteApiResponse(String tableName, InputStream jsonIn
throw new BigQueryException("Failed to append records. \n" + e);
}
- // Finalize the stream before commiting it
+ // Finalize the stream before committing it
writer.finalizeWriteStream();
BatchCommitWriteStreamsResponse commitResponse = getCommitResponse(parentTable, writer);
@@ -381,7 +343,7 @@ public WriteApiResponse getWriteApiResponse(String tableName, InputStream jsonIn
}
}
- // set isSucccessful flag to true of there were no errors
+ // set isSuccessful flag to true of there were no errors
if (apiResponse.getErrors().isEmpty()) {
apiResponse.setSuccessful(true);
}
@@ -423,9 +385,9 @@ public int getJsonWriterBatchSize() {
return this.jsonWriterBatchSize;
}
- private SettableListenableFuture createJobFuture(Job pendingJob) {
- // Prepare the polling task for the ListenableFuture result returned to end-user
- SettableListenableFuture result = new SettableListenableFuture<>();
+ private CompletableFuture createJobFuture(Job pendingJob) {
+ // Prepare the polling task for the CompletableFuture result returned to end-user
+ CompletableFuture result = new CompletableFuture<>();
ScheduledFuture> scheduledFuture =
taskScheduler.scheduleAtFixedRate(
() -> {
@@ -433,22 +395,25 @@ private SettableListenableFuture createJobFuture(Job pendingJob) {
Job job = pendingJob.reload();
if (State.DONE.equals(job.getStatus().getState())) {
if (job.getStatus().getError() != null) {
- result.setException(
+ result.completeExceptionally(
new BigQueryException(job.getStatus().getError().getMessage()));
} else {
- result.set(job);
+ result.complete(job);
}
}
} catch (Exception e) {
- result.setException(new BigQueryException(e.getMessage()));
+ result.completeExceptionally(new BigQueryException(e.getMessage()));
}
},
this.jobPollInterval);
- result.addCallback(
- response -> scheduledFuture.cancel(true),
- response -> {
- pendingJob.cancel();
+ result.whenComplete(
+ (response, exception) -> {
+ if (exception != null) {
+ pendingJob.cancel();
+ scheduledFuture.cancel(true);
+ return;
+ }
scheduledFuture.cancel(true);
});
diff --git a/spring-cloud-gcp-bigquery/src/main/java/com/google/cloud/spring/bigquery/integration/outbound/BigQueryFileMessageHandler.java b/spring-cloud-gcp-bigquery/src/main/java/com/google/cloud/spring/bigquery/integration/outbound/BigQueryFileMessageHandler.java
index 70084d8cb4..f2c5e2d080 100644
--- a/spring-cloud-gcp-bigquery/src/main/java/com/google/cloud/spring/bigquery/integration/outbound/BigQueryFileMessageHandler.java
+++ b/spring-cloud-gcp-bigquery/src/main/java/com/google/cloud/spring/bigquery/integration/outbound/BigQueryFileMessageHandler.java
@@ -29,6 +29,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -43,7 +44,6 @@
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandlingException;
import org.springframework.util.Assert;
-import org.springframework.util.concurrent.ListenableFuture;
/**
* A {@link org.springframework.messaging.MessageHandler} which handles sending and loading files to
@@ -166,7 +166,7 @@ public void setTimeout(Duration timeout) {
*
* If set to true, the handler runs synchronously and returns {@link Job} for message
* responses. If set to false, the handler will return {@link
- * org.springframework.util.concurrent.ListenableFuture} of the Job as the response for each
+ * CompletableFuture} of the Job as the response for each
* message.
*
* @param sync whether {@link BigQueryFileMessageHandler} should wait synchronously for jobs to
@@ -189,7 +189,7 @@ protected Object handleRequestMessage(Message> message) {
Assert.notNull(formatOptions, "Data file formatOptions must not be null.");
try (InputStream inputStream = convertToInputStream(message.getPayload())) {
- ListenableFuture jobFuture =
+ CompletableFuture jobFuture =
this.bigQueryTemplate.writeDataToTable(tableName, inputStream, formatOptions, schema);
if (this.sync) {
@@ -216,14 +216,14 @@ protected Object handleRequestMessage(Message> message) {
private static InputStream convertToInputStream(Object payload) throws IOException {
InputStream result;
- if (payload instanceof File) {
- result = new BufferedInputStream(new FileInputStream((File) payload));
- } else if (payload instanceof byte[]) {
- result = new ByteArrayInputStream((byte[]) payload);
- } else if (payload instanceof InputStream) {
- result = (InputStream) payload;
- } else if (payload instanceof Resource) {
- result = ((Resource) payload).getInputStream();
+ if (payload instanceof File file) {
+ result = new BufferedInputStream(new FileInputStream(file));
+ } else if (payload instanceof byte[] bytes) {
+ result = new ByteArrayInputStream(bytes);
+ } else if (payload instanceof InputStream inputStream) {
+ result = inputStream;
+ } else if (payload instanceof Resource resource) {
+ result = resource.getInputStream();
} else {
throw new IllegalArgumentException(
String.format(
diff --git a/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/BigQueryTemplateTest.java b/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/BigQueryTemplateTest.java
index 5ef86e4a15..59ba2c4a80 100644
--- a/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/BigQueryTemplateTest.java
+++ b/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/BigQueryTemplateTest.java
@@ -16,9 +16,15 @@
package com.google.cloud.spring.bigquery;
+import static com.google.cloud.bigquery.JobInfo.CreateDisposition.CREATE_IF_NEEDED;
+import static com.google.cloud.bigquery.JobInfo.CreateDisposition.CREATE_NEVER;
+import static com.google.cloud.bigquery.JobInfo.WriteDisposition.WRITE_APPEND;
+import static com.google.cloud.bigquery.JobInfo.WriteDisposition.WRITE_EMPTY;
+import static com.google.cloud.bigquery.JobInfo.WriteDisposition.WRITE_TRUNCATE;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
@@ -47,6 +53,7 @@
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -54,13 +61,12 @@
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler;
-import org.springframework.util.concurrent.ListenableFuture;
@ExtendWith(MockitoExtension.class)
class BigQueryTemplateTest {
private BigQueryWriteClient bigQueryWriteClientMock;
- private String newLineSeperatedJson =
+ private final String newLineSeperatedJson =
"{\"CompanyName\":\"TALES\",\"Description\":\"mark\",\"SerialNumber\":97,\"Leave\":0,\"EmpName\":\"Mark\"}\n"
+ "{\"CompanyName\":\"1Q84\",\"Description\":\"ark\",\"SerialNumber\":978,\"Leave\":0,\"EmpName\":\"HARUKI\"}";
private static final String PROJECT = "project";
@@ -72,7 +78,7 @@ class BigQueryTemplateTest {
private BigQueryRpc bigqueryRpcMock;
private BigQuery bigquery;
private BigQueryOptions options;
- private Map bqInitSettings = new HashMap<>();
+ private final Map bqInitSettings = new HashMap<>();
BigQueryTemplate bqTemplateSpy;
private Schema getDefaultSchema() {
@@ -92,7 +98,7 @@ public void setUp() {
rpcFactoryMock = mock(BigQueryRpcFactory.class);
bigqueryRpcMock = mock(BigQueryRpc.class);
when(rpcFactoryMock.create(any(BigQueryOptions.class))).thenReturn(bigqueryRpcMock);
- options = createBigQueryOptionsForProject(PROJECT, rpcFactoryMock);
+ options = createBigQueryOptionsForProject(rpcFactoryMock);
bigQueryWriteClientMock = mock(BigQueryWriteClient.class);
bigquery = options.getService();
bqInitSettings.put("DATASET_NAME", DATASET);
@@ -105,19 +111,82 @@ public void setUp() {
}
private BigQueryOptions createBigQueryOptionsForProject(
- String project, BigQueryRpcFactory rpcFactory) {
+ BigQueryRpcFactory rpcFactory) {
return BigQueryOptions.newBuilder()
- .setProjectId(project)
+ .setProjectId(BigQueryTemplateTest.PROJECT)
.setServiceRpcFactory(rpcFactory)
.setRetrySettings(ServiceOptions.getNoRetrySettings())
.build();
}
+ @Test
+ void getDatasetNameTest() {
+ assertThat(bqTemplateSpy.getDatasetName()).isEqualTo(DATASET);
+ }
+
+ @Test
+ void getJsonWriterBatchSizeTest() {
+ assertThat(bqTemplateSpy.getJsonWriterBatchSize()).isEqualTo(JSON_WRITER_BATCH_SIZE);
+ }
+
+ @Test
+ void setAutoDetectSchemaTest() {
+ assertThatCode(() -> bqTemplateSpy.setAutoDetectSchema(true))
+ .doesNotThrowAnyException();
+ assertThatCode(() -> bqTemplateSpy.setAutoDetectSchema(false))
+ .doesNotThrowAnyException();
+ }
+
+ @Test
+ void setWriteDispositionTest() {
+ assertThatCode(() -> bqTemplateSpy.setWriteDisposition(WRITE_TRUNCATE))
+ .doesNotThrowAnyException();
+ assertThatCode(() -> bqTemplateSpy.setWriteDisposition(WRITE_APPEND))
+ .doesNotThrowAnyException();
+ assertThatCode(() -> bqTemplateSpy.setWriteDisposition(WRITE_EMPTY))
+ .doesNotThrowAnyException();
+ }
+
+ @Test
+ void setWriteDispositionThrowsExceptionTest() {
+ assertThatCode(() -> bqTemplateSpy.setWriteDisposition(null))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasStackTraceContaining("BigQuery write disposition must not be null.");
+ }
+
+ @Test
+ void setCreateDispositionTest() {
+ assertThatCode(() -> bqTemplateSpy.setCreateDisposition(CREATE_IF_NEEDED))
+ .doesNotThrowAnyException();
+ assertThatCode(() -> bqTemplateSpy.setCreateDisposition(CREATE_NEVER))
+ .doesNotThrowAnyException();
+ }
+
+ @Test
+ void setCreateDispositionThrowsExceptionTest() {
+ assertThatCode(() -> bqTemplateSpy.setCreateDisposition(null))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasStackTraceContaining("BigQuery create disposition must not be null.");
+ }
+
+ @Test
+ void setJobPollIntervalTest() {
+ assertThatCode(() -> bqTemplateSpy.setJobPollInterval(Duration.ofSeconds(1L)))
+ .doesNotThrowAnyException();
+ }
+
+ @Test
+ void setJobPollIntervalThrowsExceptionTest() {
+ assertThatCode(() -> bqTemplateSpy.setJobPollInterval(null))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasStackTraceContaining("BigQuery job polling interval must not be null");
+ }
+
@Test
void getWriteApiResponseTest()
throws DescriptorValidationException, IOException, InterruptedException {
- InputStream jsoninputStream = new ByteArrayInputStream(newLineSeperatedJson.getBytes());
+ InputStream jsonInputStream = new ByteArrayInputStream(newLineSeperatedJson.getBytes());
doReturn(mock(BigQueryJsonDataWriter.class))
.when(bqTemplateSpy)
@@ -130,7 +199,7 @@ void getWriteApiResponseTest()
.when(bqTemplateSpy)
.getCommitResponse(any(TableName.class), any(BigQueryJsonDataWriter.class));
- WriteApiResponse apiRes = bqTemplateSpy.getWriteApiResponse(TABLE, jsoninputStream);
+ WriteApiResponse apiRes = bqTemplateSpy.getWriteApiResponse(TABLE, jsonInputStream);
assertTrue(apiRes.isSuccessful());
assertEquals(0, apiRes.getErrors().size());
@@ -140,15 +209,15 @@ void getWriteApiResponseTest()
void writeJsonStreamTest()
throws DescriptorValidationException, IOException, InterruptedException, ExecutionException {
- InputStream jsoninputStream = new ByteArrayInputStream(newLineSeperatedJson.getBytes());
+ InputStream jsonInputStream = new ByteArrayInputStream(newLineSeperatedJson.getBytes());
WriteApiResponse apiResponse = new WriteApiResponse();
apiResponse.setSuccessful(true);
doReturn(apiResponse)
.when(bqTemplateSpy)
.getWriteApiResponse(any(String.class), any(InputStream.class));
- ListenableFuture futRes =
- bqTemplateSpy.writeJsonStream(TABLE, jsoninputStream);
+ CompletableFuture futRes =
+ bqTemplateSpy.writeJsonStream(TABLE, jsonInputStream);
WriteApiResponse apiRes = futRes.get();
assertTrue(apiRes.isSuccessful());
assertEquals(0, apiRes.getErrors().size());
@@ -158,7 +227,7 @@ void writeJsonStreamTest()
void writeJsonStreamWithSchemaTest()
throws DescriptorValidationException, IOException, InterruptedException, ExecutionException {
- InputStream jsoninputStream = new ByteArrayInputStream(newLineSeperatedJson.getBytes());
+ InputStream jsonInputStream = new ByteArrayInputStream(newLineSeperatedJson.getBytes());
WriteApiResponse apiResponse = new WriteApiResponse();
apiResponse.setSuccessful(true);
doReturn(apiResponse)
@@ -169,8 +238,8 @@ void writeJsonStreamWithSchemaTest()
.when(bqTemplateSpy)
.createTable(any(String.class), any(Schema.class));
- ListenableFuture futRes =
- bqTemplateSpy.writeJsonStream(TABLE, jsoninputStream, getDefaultSchema());
+ CompletableFuture futRes =
+ bqTemplateSpy.writeJsonStream(TABLE, jsonInputStream, getDefaultSchema());
WriteApiResponse apiRes = futRes.get();
assertTrue(apiRes.isSuccessful());
assertEquals(0, apiRes.getErrors().size());
@@ -179,9 +248,9 @@ void writeJsonStreamWithSchemaTest()
@Test
void writeJsonStreamFailsOnGenericWritingException()
- throws DescriptorValidationException, IOException, InterruptedException, ExecutionException {
+ throws DescriptorValidationException, IOException, InterruptedException {
- InputStream jsoninputStream = new ByteArrayInputStream(newLineSeperatedJson.getBytes());
+ InputStream jsonInputStream = new ByteArrayInputStream(newLineSeperatedJson.getBytes());
doReturn(mock(Table.class))
.when(bqTemplateSpy)
.createTable(any(String.class), any(Schema.class));
@@ -190,8 +259,8 @@ void writeJsonStreamFailsOnGenericWritingException()
.when(bqTemplateSpy)
.getWriteApiResponse(any(String.class), any(InputStream.class));
- ListenableFuture futRes =
- bqTemplateSpy.writeJsonStream(TABLE, jsoninputStream, getDefaultSchema());
+ CompletableFuture futRes =
+ bqTemplateSpy.writeJsonStream(TABLE, jsonInputStream, getDefaultSchema());
assertThat(futRes)
.withFailMessage("boom!")
.failsWithin(Duration.ofSeconds(1));
diff --git a/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/core/BigQueryTemplateIntegrationTests.java b/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/core/BigQueryTemplateIntegrationTests.java
index 7eddc83f89..5b64e905f5 100644
--- a/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/core/BigQueryTemplateIntegrationTests.java
+++ b/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/core/BigQueryTemplateIntegrationTests.java
@@ -32,10 +32,9 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
-import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
@@ -46,7 +45,6 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.Resource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
-import org.springframework.util.concurrent.ListenableFuture;
/**
* Integration tests for BigQuery.
@@ -102,7 +100,7 @@ void testLoadFileWithSchema() throws Exception {
Field.of("State", StandardSQLTypeName.STRING),
Field.of("County", StandardSQLTypeName.STRING));
- ListenableFuture bigQueryJobFuture =
+ CompletableFuture bigQueryJobFuture =
bigQueryTemplate.writeDataToTable(
tableName, dataFile.getInputStream(), FormatOptions.csv(), schema);
@@ -128,7 +126,7 @@ void testJsonFileLoadWithSchema() throws Exception {
Field.of("Leave", StandardSQLTypeName.NUMERIC),
Field.of("EmpName", StandardSQLTypeName.STRING));
- ListenableFuture writeApiFuture =
+ CompletableFuture writeApiFuture =
bigQueryTemplate.writeJsonStream(tableName, jsonDataFile.getInputStream(), schema);
WriteApiResponse writeApiResponse =
@@ -146,7 +144,7 @@ void testJsonFileLoadWithSchema() throws Exception {
@Test
void testLoadFile() throws IOException, ExecutionException, InterruptedException {
- ListenableFuture bigQueryJobFuture =
+ CompletableFuture bigQueryJobFuture =
bigQueryTemplate.writeDataToTable(
this.tableName, dataFile.getInputStream(), FormatOptions.csv());
@@ -167,7 +165,7 @@ void testLoadBytes() throws ExecutionException, InterruptedException {
byte[] byteArray = "CountyId,State,County\n1001,Alabama,Autauga County\n".getBytes();
ByteArrayInputStream byteStream = new ByteArrayInputStream(byteArray);
- ListenableFuture bigQueryJobFuture =
+ CompletableFuture bigQueryJobFuture =
bigQueryTemplate.writeDataToTable(this.tableName, byteStream, FormatOptions.csv());
Job job = bigQueryJobFuture.get();
diff --git a/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/integration/outbound/BigQueryFileMessageHandlerIntegrationTests.java b/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/integration/outbound/BigQueryFileMessageHandlerIntegrationTests.java
index 7a22c7d4d9..3a0d886122 100644
--- a/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/integration/outbound/BigQueryFileMessageHandlerIntegrationTests.java
+++ b/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/integration/outbound/BigQueryFileMessageHandlerIntegrationTests.java
@@ -35,6 +35,7 @@
import java.io.File;
import java.time.Duration;
import java.util.HashMap;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.AfterEach;
@@ -51,7 +52,6 @@
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.junit.jupiter.SpringExtension;
-import org.springframework.util.concurrent.ListenableFuture;
@EnabledIfSystemProperty(named = "it.bigquery", matches = "true")
@ExtendWith(SpringExtension.class)
@@ -91,8 +91,8 @@ void testLoadFileWithSchema() throws InterruptedException, ExecutionException {
MessageBuilder.createMessage(
new File("src/test/resources/data.csv"), new MessageHeaders(messageHeaders));
- ListenableFuture jobFuture =
- (ListenableFuture) this.messageHandler.handleRequestMessage(message);
+ CompletableFuture jobFuture =
+ (CompletableFuture) this.messageHandler.handleRequestMessage(message);
// Assert that a BigQuery polling task is scheduled successfully.
await()
@@ -126,8 +126,8 @@ void testLoadFile() throws InterruptedException, ExecutionException {
MessageBuilder.createMessage(
new File("src/test/resources/data.csv"), new MessageHeaders(messageHeaders));
- ListenableFuture jobFuture =
- (ListenableFuture) this.messageHandler.handleRequestMessage(message);
+ CompletableFuture jobFuture =
+ (CompletableFuture) this.messageHandler.handleRequestMessage(message);
// Assert that a BigQuery polling task is scheduled successfully.
await()
@@ -181,8 +181,8 @@ void testLoadFile_cancel() {
MessageBuilder.createMessage(
new File("src/test/resources/data.csv"), new MessageHeaders(messageHeaders));
- ListenableFuture> jobFuture =
- (ListenableFuture>) this.messageHandler.handleRequestMessage(message);
+ CompletableFuture> jobFuture =
+ (CompletableFuture>) this.messageHandler.handleRequestMessage(message);
assertThat(jobFuture).isNotNull();
jobFuture.cancel(true);
diff --git a/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/integration/outbound/BigQueryFileMessageHandlerTests.java b/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/integration/outbound/BigQueryFileMessageHandlerTests.java
index 0d235bd4e4..29a2fb52f1 100644
--- a/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/integration/outbound/BigQueryFileMessageHandlerTests.java
+++ b/spring-cloud-gcp-bigquery/src/test/java/com/google/cloud/spring/bigquery/integration/outbound/BigQueryFileMessageHandlerTests.java
@@ -17,6 +17,7 @@
package com.google.cloud.spring.bigquery.integration.outbound;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -26,16 +27,24 @@
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.Schema;
import com.google.cloud.spring.bigquery.core.BigQueryTemplate;
+import java.io.IOException;
import java.io.InputStream;
+import java.math.BigInteger;
+import java.time.Duration;
import java.util.Collections;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.core.io.Resource;
+import org.springframework.expression.Expression;
import org.springframework.integration.expression.ValueExpression;
import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageHandlingException;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder;
-import org.springframework.util.concurrent.ListenableFuture;
-import org.springframework.util.concurrent.SettableListenableFuture;
class BigQueryFileMessageHandlerTests {
@@ -43,23 +52,48 @@ class BigQueryFileMessageHandlerTests {
private BigQueryFileMessageHandler messageHandler;
+ private final CompletableFuture completableFuture = new CompletableFuture<>();
+
@BeforeEach
void setup() {
bigQueryTemplate = mock(BigQueryTemplate.class);
- SettableListenableFuture result = new SettableListenableFuture<>();
- result.set(mock(Job.class));
- when(bigQueryTemplate.writeDataToTable(any(), any(), any(), any())).thenReturn(result);
-
+ completableFuture.complete(mock(Job.class));
+ when(bigQueryTemplate.writeDataToTable(any(), any(), any(), any())).thenReturn(
+ completableFuture);
messageHandler = new BigQueryFileMessageHandler(bigQueryTemplate);
- }
-
- @Test
- void testHandleMessage_async() {
messageHandler.setTableName("testTable");
messageHandler.setFormatOptions(FormatOptions.csv());
messageHandler.setSync(false);
messageHandler.setTableSchema(Schema.of());
+ }
+
+ @Test
+ void testHandleResourceMessage() throws IOException {
+ Resource payload = mock(Resource.class);
+ Message> message =
+ MessageBuilder.createMessage(payload, new MessageHeaders(Collections.emptyMap()));
+
+ Object result = messageHandler.handleRequestMessage(message);
+ verify(bigQueryTemplate)
+ .writeDataToTable("testTable", payload.getInputStream(), FormatOptions.csv(), Schema.of());
+ assertThat(result).isNotNull().isInstanceOf(CompletableFuture.class);
+ }
+
+ @Test
+ void testHandleResourceMessageThrowsException() throws IOException {
+ Resource payload = mock(Resource.class);
+ when(payload.getInputStream()).thenThrow(IOException.class);
+ Message> message =
+ MessageBuilder.createMessage(payload, new MessageHeaders(Collections.emptyMap()));
+
+ assertThatCode(() -> messageHandler.handleRequestMessage(message))
+ .isInstanceOf(MessageHandlingException.class)
+ .hasStackTraceContaining("Failed to write data to BigQuery tables in message handler");
+ }
+
+ @Test
+ void testHandleInputStreamMessage_async() {
InputStream payload = mock(InputStream.class);
Message> message =
MessageBuilder.createMessage(payload, new MessageHeaders(Collections.emptyMap()));
@@ -68,13 +102,11 @@ void testHandleMessage_async() {
verify(bigQueryTemplate)
.writeDataToTable("testTable", payload, FormatOptions.csv(), Schema.of());
- assertThat(result).isNotNull().isInstanceOf(ListenableFuture.class);
+ assertThat(result).isNotNull().isInstanceOf(CompletableFuture.class);
}
@Test
void testHandleMessage_sync() {
- messageHandler.setTableName("testTable");
- messageHandler.setFormatOptions(FormatOptions.csv());
messageHandler.setSync(true);
messageHandler.setTableSchemaExpression(new ValueExpression<>(Schema.of()));
@@ -88,4 +120,101 @@ void testHandleMessage_sync() {
.writeDataToTable("testTable", payload, FormatOptions.csv(), Schema.of());
assertThat(result).isNotNull().isInstanceOf(Job.class);
}
+
+ @Test
+ void testHandleMessage_ThrowsExecutionExceptionTest()
+ throws ExecutionException, InterruptedException, TimeoutException {
+ CompletableFuture mockCompletableFuture = mock(CompletableFuture.class);
+ when(bigQueryTemplate.writeDataToTable(any(), any(), any(), any())).thenReturn(
+ mockCompletableFuture);
+ when(mockCompletableFuture.get(1L, TimeUnit.SECONDS))
+ .thenThrow(ExecutionException.class);
+ messageHandler.setSync(true);
+ messageHandler.setTableSchemaExpression(new ValueExpression<>(Schema.of()));
+ messageHandler.setTimeout(Duration.ofSeconds(1));
+ InputStream payload = mock(InputStream.class);
+ Message> message =
+ MessageBuilder.createMessage(payload, new MessageHeaders(Collections.emptyMap()));
+
+ assertThatCode(() -> messageHandler.handleRequestMessage(message))
+ .isInstanceOf(MessageHandlingException.class)
+ .hasStackTraceContaining("Failed to wait for BigQuery Job to complete in message handler");
+ }
+
+ @Test
+ void testHandleMessage_ThrowsInterruptedExceptionTest()
+ throws ExecutionException, InterruptedException, TimeoutException {
+ CompletableFuture mockCompletableFuture = mock(CompletableFuture.class);
+ when(bigQueryTemplate.writeDataToTable(any(), any(), any(), any())).thenReturn(
+ mockCompletableFuture);
+ when(mockCompletableFuture.get(1L, TimeUnit.SECONDS))
+ .thenThrow(InterruptedException.class);
+ messageHandler.setSync(true);
+ messageHandler.setTableSchemaExpression(new ValueExpression<>(Schema.of()));
+ messageHandler.setTimeout(Duration.ofSeconds(1));
+ InputStream payload = mock(InputStream.class);
+ Message> message =
+ MessageBuilder.createMessage(payload, new MessageHeaders(Collections.emptyMap()));
+
+ assertThatCode(() -> messageHandler.handleRequestMessage(message))
+ .isInstanceOf(MessageHandlingException.class)
+ .hasStackTraceContaining("Failed to wait for BigQuery Job (interrupted) in message handler");
+ }
+
+ @Test
+ void testHandleMessageWithIllegalArgumentTest() {
+ messageHandler.setSync(true);
+ messageHandler.setTableSchemaExpression(new ValueExpression<>(Schema.of()));
+
+ BigInteger payload = mock(BigInteger.class);
+ Message> message =
+ MessageBuilder.createMessage(payload, new MessageHeaders(Collections.emptyMap()));
+
+ assertThatCode(() -> messageHandler.handleRequestMessage(message))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage(String.format(
+ "Unsupported message payload type: %s. The supported payload types "
+ + "are: java.io.File, byte[], org.springframework.core.io.Resource, "
+ + "and java.io.InputStream.",
+ payload.getClass().getName()));
+ }
+
+ @Test
+ void setTableNameExpressionThrowsExceptionTest() {
+ assertThatCode(() -> messageHandler.setTableNameExpression(null))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Table name expression must not be null.");
+ }
+
+ @Test
+ void setTableNameExpressionTest() {
+ assertThatCode(() -> messageHandler.setTableNameExpression(mock(Expression.class)))
+ .doesNotThrowAnyException();
+ }
+
+ @Test
+ void setFormatOptionsExpressionThrowsExceptionTest() {
+ assertThatCode(() -> messageHandler.setFormatOptionsExpression(null))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Format options expression cannot be null.");
+ }
+
+ @Test
+ void setFormatOptionsExpressionTest() {
+ assertThatCode(() -> messageHandler.setFormatOptionsExpression(mock(Expression.class)))
+ .doesNotThrowAnyException();
+ }
+
+ @Test
+ void setTimeOutThrowsExceptionTest() {
+ assertThatCode(() -> messageHandler.setTimeout(null))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Timeout duration must not be null.");
+ }
+
+ @Test
+ void setTimeOutTest() {
+ assertThatCode(() -> messageHandler.setTimeout(Duration.ZERO))
+ .doesNotThrowAnyException();
+ }
}
diff --git a/spring-cloud-gcp-cloudfoundry/pom.xml b/spring-cloud-gcp-cloudfoundry/pom.xml
index 2550c3bdce..82aecb23f9 100644
--- a/spring-cloud-gcp-cloudfoundry/pom.xml
+++ b/spring-cloud-gcp-cloudfoundry/pom.xml
@@ -7,7 +7,7 @@
spring-cloud-gcp
com.google.cloud
- 3.4.3-SNAPSHOT
+ 4.0.0-SNAPSHOT
spring-cloud-gcp-cloudfoundry
diff --git a/spring-cloud-gcp-core/pom.xml b/spring-cloud-gcp-core/pom.xml
index 58897e6960..30b64e8758 100644
--- a/spring-cloud-gcp-core/pom.xml
+++ b/spring-cloud-gcp-core/pom.xml
@@ -6,7 +6,7 @@
spring-cloud-gcp
com.google.cloud
- 3.4.3-SNAPSHOT
+ 4.0.0-SNAPSHOT
spring-cloud-gcp-core
diff --git a/spring-cloud-gcp-data-datastore/pom.xml b/spring-cloud-gcp-data-datastore/pom.xml
index b7c698dc56..6fa3dafb67 100644
--- a/spring-cloud-gcp-data-datastore/pom.xml
+++ b/spring-cloud-gcp-data-datastore/pom.xml
@@ -7,9 +7,8 @@
spring-cloud-gcp
com.google.cloud
- 3.4.3-SNAPSHOT
+ 4.0.0-SNAPSHOT
- com.google.cloud
spring-cloud-gcp-data-datastore
Spring Framework on Google Cloud Module - Datastore
Spring Framework on Google Cloud Datastore Module
diff --git a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/DatastoreTemplate.java b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/DatastoreTemplate.java
index f5e4cf06de..662985815b 100644
--- a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/DatastoreTemplate.java
+++ b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/DatastoreTemplate.java
@@ -84,7 +84,7 @@
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
-import org.springframework.data.util.ClassTypeInformation;
+import org.springframework.data.util.TypeInformation;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@@ -249,7 +249,7 @@ private Collection performFindByKey(Iterable> ids, Class entityClass
}
private List findAllById(Set keys, Class entityClass, ReadContext context) {
- List missingKeys = keys.stream().filter(context::notCached).collect(Collectors.toList());
+ List missingKeys = keys.stream().filter(context::notCached).toList();
if (!missingKeys.isEmpty()) {
List entities = getDatastoreReadWriter().fetch(missingKeys.toArray(new Key[] {}));
@@ -305,8 +305,8 @@ private StructuredQuery applyPageable(StructuredQuery query, Pageable pageable)
return query;
}
Cursor cursor = null;
- if (pageable instanceof DatastorePageable) {
- cursor = ((DatastorePageable) pageable).toCursor();
+ if (pageable instanceof DatastorePageable datastorePageable) {
+ cursor = datastorePageable.toCursor();
}
StructuredQuery.Builder builder = query.toBuilder();
if (cursor != null) {
@@ -470,7 +470,7 @@ public Map findByIdAsMap(Key key, Class valueType) {
Entity entity = getDatastoreReadWriter().get(key);
return this.datastoreEntityConverter.readAsMap(
- String.class, ClassTypeInformation.from(valueType), entity);
+ String.class, TypeInformation.of(valueType), entity);
}
@Override
@@ -561,7 +561,7 @@ private List getReferenceEntitiesForSave(
List keyValues =
StreamSupport.stream((iterableVal).spliterator(), false)
.map(o -> KeyValue.of(this.getKey(o, false)))
- .collect(Collectors.toList());
+ .toList();
value = ListValue.of(keyValues);
} else {
@@ -656,7 +656,7 @@ private List convertEntitiesForRead(
return keys.stream()
.map(key -> convertEntityResolveDescendantsAndReferences(entityClass, key, context))
.filter(Objects::nonNull)
- .collect(Collectors.toList());
+ .toList();
}
private T convertEntityResolveDescendantsAndReferences(
diff --git a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/convert/DatastoreCustomConversions.java b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/convert/DatastoreCustomConversions.java
index d6d078cd1f..fd2e886664 100644
--- a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/convert/DatastoreCustomConversions.java
+++ b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/convert/DatastoreCustomConversions.java
@@ -24,9 +24,8 @@
import java.util.List;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.CustomConversions;
-import org.springframework.data.convert.JodaTimeConverters;
import org.springframework.data.convert.Jsr310Converters;
-import org.springframework.data.convert.ThreeTenBackPortConverters;
+import org.springframework.lang.NonNull;
/**
* Value object to capture custom conversion. {@link DatastoreCustomConversions}
@@ -41,17 +40,15 @@ public class DatastoreCustomConversions extends CustomConversions {
static {
ArrayList> converters = new ArrayList<>();
- converters.addAll(JodaTimeConverters.getConvertersToRegister());
converters.addAll(Jsr310Converters.getConvertersToRegister());
- converters.addAll(ThreeTenBackPortConverters.getConvertersToRegister());
converters.add(
new Converter() {
@Override
- public Long convert(BaseKey key) {
+ public Long convert(@NonNull BaseKey baseKey) {
Long id = null;
// embedded entities have IncompleteKey, and have no inner value
- if (key instanceof Key) {
- id = ((Key) key).getId();
+ if (baseKey instanceof Key key) {
+ id = key.getId();
if (id == null) {
throw new DatastoreDataException(
"The given key doesn't have a numeric ID but a conversion"
@@ -65,11 +62,11 @@ public Long convert(BaseKey key) {
converters.add(
new Converter() {
@Override
- public String convert(BaseKey key) {
+ public String convert(@NonNull BaseKey baseKey) {
String name = null;
// embedded entities have IncompleteKey, and have no inner value
- if (key instanceof Key) {
- name = ((Key) key).getName();
+ if (baseKey instanceof Key key) {
+ name = key.getName();
if (name == null) {
throw new DatastoreDataException(
"The given key doesn't have a String name value but "
diff --git a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/convert/DefaultDatastoreEntityConverter.java b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/convert/DefaultDatastoreEntityConverter.java
index 1717655e40..8f9f18c2e7 100644
--- a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/convert/DefaultDatastoreEntityConverter.java
+++ b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/convert/DefaultDatastoreEntityConverter.java
@@ -36,14 +36,13 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.stream.Collectors;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.model.EntityInstantiator;
import org.springframework.data.mapping.model.EntityInstantiators;
import org.springframework.data.mapping.model.ParameterValueProvider;
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
-import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
+import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
/**
@@ -52,7 +51,7 @@
* @since 1.1
*/
public class DefaultDatastoreEntityConverter implements DatastoreEntityConverter {
- private DatastoreMappingContext mappingContext;
+ private final DatastoreMappingContext mappingContext;
private final EntityInstantiators instantiators = new EntityInstantiators();
@@ -123,7 +122,7 @@ public Map readAsMap(
if (entity == null) {
return null;
}
- return readAsMap(entity, ClassTypeInformation.from(HashMap.class));
+ return readAsMap(entity, TypeInformation.of(HashMap.class));
}
public DatastorePersistentEntity getDiscriminationPersistentEntity(
@@ -172,7 +171,7 @@ public R read(Class clazz, BaseEntity entity) {
persistentEntity.doWithColumnBackedProperties(
datastorePersistentProperty -> {
// if a property is a constructor argument, it was already computed on instantiation
- if (!persistentEntity.isConstructorArgument(datastorePersistentProperty)) {
+ if (!persistentEntity.isCreatorArgument(datastorePersistentProperty)) {
Object value = propertyValueProvider.getPropertyValue(datastorePersistentProperty);
if (value != null) {
accessor.setProperty(datastorePersistentProperty, value);
@@ -213,13 +212,13 @@ private boolean isDiscriminationFieldMatch(
propertyValueProvider.getPropertyValue(
entity.getDiscriminationFieldName(),
NOT_EMBEDDED,
- ClassTypeInformation.from(String[].class)))
+ TypeInformation.of(String[].class)))
[0].equals(entity.getDiscriminatorValue());
}
@Override
@SuppressWarnings("unchecked")
- public void write(Object source, BaseEntity.Builder sink) {
+ public void write(Object source, @NonNull BaseEntity.Builder sink) {
DatastorePersistentEntity> persistentEntity =
this.mappingContext.getDatastorePersistentEntity(source.getClass());
@@ -228,7 +227,7 @@ public void write(Object source, BaseEntity.Builder sink) {
if (!discriminationValues.isEmpty() || discriminationFieldName != null) {
sink.set(
discriminationFieldName,
- discriminationValues.stream().map(StringValue::of).collect(Collectors.toList()));
+ discriminationValues.stream().map(StringValue::of).toList());
}
PersistentPropertyAccessor accessor = persistentEntity.getPropertyAccessor(source);
persistentEntity.doWithColumnBackedProperties(
@@ -271,7 +270,7 @@ private Value setExcludeFromIndexes(Value convertedVal) {
return ListValue.of(
(List)
((ListValue) convertedVal)
- .get().stream().map(this::setExcludeFromIndexes).collect(Collectors.toList()));
+ .get().stream().map(this::setExcludeFromIndexes).toList());
} else {
return convertedVal.toBuilder().setExcludeFromIndexes(true).build();
}
diff --git a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/convert/TwoStepsConversions.java b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/convert/TwoStepsConversions.java
index 09eee40c10..144f1c5ff6 100644
--- a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/convert/TwoStepsConversions.java
+++ b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/convert/TwoStepsConversions.java
@@ -34,12 +34,12 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
-import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.springframework.core.convert.ConversionException;
import org.springframework.core.convert.converter.Converter;
@@ -47,7 +47,6 @@
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.mapping.PersistentEntity;
-import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -62,7 +61,7 @@
*/
public class TwoStepsConversions implements ReadWriteConversions {
private static final Converter BLOB_TO_BYTE_ARRAY_CONVERTER =
- new Converter() {
+ new Converter<>() {
@Override
public byte[] convert(Blob source) {
return source.toByteArray();
@@ -70,7 +69,7 @@ public byte[] convert(Blob source) {
};
private static final Converter BYTE_ARRAY_TO_BLOB_CONVERTER =
- new Converter() {
+ new Converter<>() {
@Override
public Blob convert(byte[] source) {
return Blob.copyFrom(source);
@@ -106,14 +105,14 @@ public TwoStepsConversions(
this.internalConversionService.addConverter(BLOB_TO_BYTE_ARRAY_CONVERTER);
}
+ @SuppressWarnings("unchecked")
@Override
public T convertOnRead(Object val, Class targetCollectionType, Class targetComponentType) {
- return (T)
- convertOnRead(
- val,
- EmbeddedType.NOT_EMBEDDED,
- targetCollectionType,
- ClassTypeInformation.from(targetComponentType));
+ return convertOnRead(
+ val,
+ EmbeddedType.NOT_EMBEDDED,
+ targetCollectionType,
+ TypeInformation.of(targetComponentType));
}
@Override
@@ -130,34 +129,25 @@ public T convertOnRead(
return convertOnRead(val, embeddedType, collectionType, componentTypeInformation);
}
+ @SuppressWarnings("unchecked")
private T convertOnRead(
Object val,
EmbeddedType embeddedType,
Class targetCollectionType,
- TypeInformation targetComponentType) {
+ TypeInformation> targetComponentType) {
if (val == null) {
return null;
}
- BiFunction, ?> readConverter;
- switch (embeddedType) {
- case EMBEDDED_MAP:
- readConverter =
- (x, typeInformation) ->
- convertOnReadSingleEmbeddedMap(
- x,
- typeInformation.getComponentType().getType(),
- typeInformation.getMapValueType(),
- targetComponentType);
- break;
- case EMBEDDED_ENTITY:
- readConverter = this::convertOnReadSingleEmbedded;
- break;
- case NOT_EMBEDDED:
- readConverter = this::convertOnReadSingle;
- break;
- default:
- throw new DatastoreDataException("Unexpected property embedded type: " + embeddedType);
- }
+ BiFunction, ?> readConverter = switch (embeddedType) {
+ case EMBEDDED_MAP -> (x, typeInformation) ->
+ convertOnReadSingleEmbeddedMap(
+ x,
+ Objects.requireNonNull(typeInformation.getComponentType()).getType(),
+ typeInformation.getMapValueType(),
+ targetComponentType);
+ case EMBEDDED_ENTITY -> this::convertOnReadSingleEmbedded;
+ case NOT_EMBEDDED -> this::convertOnReadSingle;
+ };
if (ValueUtil.isCollectionLike(val.getClass())
&& targetCollectionType != null
@@ -166,15 +156,15 @@ private T convertOnRead(
try {
Assert.isInstanceOf(
Iterable.class, val, "Value passed to convertOnRead expected to be Iterable");
- List elements =
+ List> elements =
StreamSupport.stream(((Iterable>) val).spliterator(), false)
.map(
v -> {
- Object o = (v instanceof Value) ? ((Value) v).get() : v;
+ Object o = (v instanceof Value) ? ((Value>) v).get() : v;
return readConverter.apply(o, targetComponentType);
})
- .collect(Collectors.toList());
- return (T) convertCollection(elements, targetCollectionType);
+ .toList();
+ return convertCollection(elements, targetCollectionType);
} catch (ConversionException | DatastoreDataException ex) {
throw new DatastoreDataException("Unable process elements of a collection", ex);
}
@@ -187,10 +177,10 @@ private Map convertOnReadSingleEmbeddedMap(
Object value,
Class keyType,
TypeInformation targetComponentType,
- TypeInformation componentType) {
+ TypeInformation> componentType) {
Assert.notNull(value, "Cannot convert a null value.");
- if (value instanceof BaseEntity) {
- return this.datastoreEntityConverter.readAsMap((BaseEntity) value, componentType);
+ if (value instanceof BaseEntity> baseEntity) {
+ return this.datastoreEntityConverter.readAsMap(baseEntity, componentType);
}
throw new DatastoreDataException(
"Embedded entity was expected, but " + value.getClass() + " found");
@@ -200,9 +190,9 @@ private Map convertOnReadSingleEmbeddedMap(
private T convertOnReadSingleEmbedded(
Object value, TypeInformation> targetTypeInformation) {
Assert.notNull(value, "Cannot convert a null value.");
- if (value instanceof BaseEntity) {
+ if (value instanceof BaseEntity> baseEntity) {
return (T)
- this.datastoreEntityConverter.read(targetTypeInformation.getType(), (BaseEntity) value);
+ this.datastoreEntityConverter.read(targetTypeInformation.getType(), baseEntity);
}
throw new DatastoreDataException(
"Embedded entity was expected, but " + value.getClass() + " found");
@@ -213,8 +203,8 @@ private T convertOnReadSingle(Object val, TypeInformation> targetTypeInfor
if (val == null) {
return null;
}
- Class targetType = boxIfNeeded(targetTypeInformation.getType());
- Class sourceType = val.getClass();
+ Class> targetType = boxIfNeeded(targetTypeInformation.getType());
+ Class> sourceType = val.getClass();
Object result = null;
TypeTargets typeTargets = computeTypeTargets(targetType);
@@ -271,27 +261,19 @@ private Value convertOnWrite(
Function writeConverter = this::convertOnWriteSingle;
if (proppertyVal != null) {
- switch (embeddedType) {
- case EMBEDDED_MAP:
- writeConverter =
- x -> convertOnWriteSingleEmbeddedMap(x, fieldName, typeInformation.getMapValueType());
- break;
- case EMBEDDED_ENTITY:
- writeConverter = x -> convertOnWriteSingleEmbedded(x, fieldName);
- break;
- case NOT_EMBEDDED:
- writeConverter = this::convertOnWriteSingle;
- break;
- default:
- throw new DatastoreDataException("Unexpected property embedded type: " + embeddedType);
- }
+ writeConverter = switch (embeddedType) {
+ case EMBEDDED_MAP -> x -> convertOnWriteSingleEmbeddedMap(x, fieldName,
+ typeInformation.getMapValueType());
+ case EMBEDDED_ENTITY -> x -> convertOnWriteSingleEmbedded(x, fieldName);
+ case NOT_EMBEDDED -> this::convertOnWriteSingle;
+ };
}
val = ValueUtil.toListIfArray(val);
- if (val instanceof Iterable) {
+ if (val instanceof Iterable> iterable) {
List> values = new ArrayList<>();
- for (Object propEltValue : (Iterable) val) {
+ for (Object propEltValue : iterable) {
values.add(writeConverter.apply(propEltValue));
}
return ListValue.of(values);
@@ -315,8 +297,8 @@ private EntityValue applyEntityValueBuilder(
.map(PersistentEntity::getIdProperty)
.map(
id ->
- this.datastoreMappingContext
- .getPersistentEntity(val.getClass())
+ Objects.requireNonNull(this.datastoreMappingContext
+ .getPersistentEntity(val.getClass()))
.getPropertyAccessor(val)
.getProperty(id));
@@ -340,7 +322,7 @@ private EntityValue convertOnWriteSingleEmbeddedMap(
String field =
convertOnReadSingle(
convertOnWriteSingle(e.getKey()).get(),
- ClassTypeInformation.from(String.class));
+ TypeInformation.of(String.class));
builder.set(
field,
convertOnWrite(
@@ -430,15 +412,8 @@ public void registerEntityConverter(DatastoreEntityConverter datastoreEntityConv
this.datastoreEntityConverter = datastoreEntityConverter;
}
- private static class TypeTargets {
- private Class> firstStepTarget;
-
- private Class> secondStepTarget;
-
- TypeTargets(Class> firstStepTarget, Class> secondStepTarget) {
- this.firstStepTarget = firstStepTarget;
- this.secondStepTarget = secondStepTarget;
- }
+ private record TypeTargets(Class> firstStepTarget,
+ Class> secondStepTarget) {
Class> getFirstStepTarget() {
return this.firstStepTarget;
diff --git a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/mapping/DatastorePersistentPropertyImpl.java b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/mapping/DatastorePersistentPropertyImpl.java
index a63e708539..a6338b6171 100644
--- a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/mapping/DatastorePersistentPropertyImpl.java
+++ b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/core/mapping/DatastorePersistentPropertyImpl.java
@@ -16,7 +16,6 @@
package com.google.cloud.spring.data.datastore.core.mapping;
-import java.util.stream.Collectors;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
@@ -24,8 +23,6 @@
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
import org.springframework.data.mapping.model.SimpleTypeHolder;
-import org.springframework.data.util.StreamUtils;
-import org.springframework.data.util.TypeInformation;
import org.springframework.util.StringUtils;
/**
@@ -130,13 +127,6 @@ private String getAnnotatedFieldName() {
return null;
}
- @Override
- public Iterable extends TypeInformation>> getPersistentEntityTypes() {
- return StreamUtils.createStreamFromIterator(super.getPersistentEntityTypes().iterator())
- .filter(typeInfo -> typeInfo.getType().isAnnotationPresent(Entity.class))
- .collect(Collectors.toList());
- }
-
@Override
public boolean isLazyLoaded() {
return findAnnotation(LazyReference.class) != null;
diff --git a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/repository/DatastoreRepository.java b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/repository/DatastoreRepository.java
index bfafab46d0..0389f0475e 100644
--- a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/repository/DatastoreRepository.java
+++ b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/repository/DatastoreRepository.java
@@ -17,6 +17,7 @@
package com.google.cloud.spring.data.datastore.repository;
import java.util.function.Function;
+import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;
@@ -28,7 +29,7 @@
* @since 1.1
*/
public interface DatastoreRepository
- extends PagingAndSortingRepository, QueryByExampleExecutor {
+ extends PagingAndSortingRepository, QueryByExampleExecutor, CrudRepository {
/**
* Performs multiple read and write operations in a single transaction.
diff --git a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/repository/config/DatastoreAuditingRegistrar.java b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/repository/config/DatastoreAuditingRegistrar.java
index 45803d1ca3..617e96c941 100644
--- a/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/repository/config/DatastoreAuditingRegistrar.java
+++ b/spring-cloud-gcp-data-datastore/src/main/java/com/google/cloud/spring/data/datastore/repository/config/DatastoreAuditingRegistrar.java
@@ -16,6 +16,7 @@
package com.google.cloud.spring.data.datastore.repository.config;
+import com.google.cloud.spring.data.datastore.core.mapping.DatastoreMappingContext;
import com.google.cloud.spring.data.datastore.repository.support.DatastoreAuditingEventListener;
import java.lang.annotation.Annotation;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -24,6 +25,7 @@
import org.springframework.data.auditing.AuditingHandler;
import org.springframework.data.auditing.config.AuditingBeanDefinitionRegistrarSupport;
import org.springframework.data.auditing.config.AuditingConfiguration;
+import org.springframework.data.mapping.context.PersistentEntities;
/**
* Registers the annotations and classes for providing auditing support in Spring Data Cloud
@@ -35,8 +37,6 @@ public class DatastoreAuditingRegistrar extends AuditingBeanDefinitionRegistrarS
private static final String AUDITING_HANDLER_BEAN_NAME = "datastoreAuditingHandler";
- private static final String MAPPING_CONTEXT_BEAN_NAME = "datastoreMappingContext";
-
@Override
protected Class extends Annotation> getAnnotation() {
return EnableDatastoreAuditing.class;
@@ -57,10 +57,9 @@ protected void registerAuditListenerBeanDefinition(
@Override
protected BeanDefinitionBuilder getAuditHandlerBeanDefinitionBuilder(
AuditingConfiguration configuration) {
- BeanDefinitionBuilder builder =
- configureDefaultAuditHandlerAttributes(
- configuration, BeanDefinitionBuilder.rootBeanDefinition(AuditingHandler.class));
- return builder.addConstructorArgReference(MAPPING_CONTEXT_BEAN_NAME);
+ return configureDefaultAuditHandlerAttributes(
+ configuration, BeanDefinitionBuilder.rootBeanDefinition(AuditingHandler.class))
+ .addConstructorArgValue(PersistentEntities.of(new DatastoreMappingContext()));
}
@Override
diff --git a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/DatastoreTemplateAuditingTests.java b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/DatastoreTemplateAuditingTests.java
index 7c102dc377..497c7eaad6 100644
--- a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/DatastoreTemplateAuditingTests.java
+++ b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/DatastoreTemplateAuditingTests.java
@@ -31,8 +31,7 @@
import com.google.cloud.spring.data.datastore.core.mapping.DatastoreMappingContext;
import com.google.cloud.spring.data.datastore.core.mapping.Entity;
import com.google.cloud.spring.data.datastore.repository.config.EnableDatastoreAuditing;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
+import java.time.Instant;
import java.util.Collections;
import java.util.Optional;
import org.junit.jupiter.api.Test;
@@ -52,7 +51,7 @@
@ContextConfiguration
class DatastoreTemplateAuditingTests {
- private static final LocalDateTime LONG_AGO = LocalDate.parse("2000-01-01").atStartOfDay();
+ private static final Instant LONG_AGO = Instant.parse("2000-01-01T00:00:00.00Z");
@Autowired DatastoreTemplate datastoreTemplate;
@Autowired Datastore datastore;
@@ -134,7 +133,7 @@ public DatastoreTemplate datastoreTemplate(
FullEntity testEntity = invocation.getArgument(0);
assertThat(testEntity.getTimestamp("lastTouched")).isNotNull();
assertThat(testEntity.getTimestamp("lastTouched"))
- .isGreaterThan(Timestamp.of(java.sql.Timestamp.valueOf(LONG_AGO)));
+ .isGreaterThan(Timestamp.of(java.sql.Timestamp.from(LONG_AGO)));
assertThat(testEntity.getString("lastUser")).isEqualTo("test_user");
return null;
});
@@ -154,6 +153,7 @@ private static class TestEntity {
@LastModifiedBy String lastUser;
- @LastModifiedDate LocalDateTime lastTouched;
+ @LastModifiedDate
+ Instant lastTouched;
}
}
diff --git a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/DatastoreTemplateTests.java b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/DatastoreTemplateTests.java
index 5f35fd7ce6..25f717d56b 100644
--- a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/DatastoreTemplateTests.java
+++ b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/DatastoreTemplateTests.java
@@ -95,7 +95,7 @@
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
-import org.springframework.data.util.ClassTypeInformation;
+import org.springframework.data.util.TypeInformation;
/** Tests for the Datastore Template. */
class DatastoreTemplateTests {
@@ -1407,7 +1407,7 @@ void findByIdAsMapTest() {
this.datastoreTemplate.findByIdAsMap(keyForMap, Long.class);
verify(this.datastoreEntityConverter, times(1))
- .readAsMap(String.class, ClassTypeInformation.from(Long.class), datastoreEntity);
+ .readAsMap(String.class, TypeInformation.of(Long.class), datastoreEntity);
}
@Test
diff --git a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/DatastoreTransactionManagerTests.java b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/DatastoreTransactionManagerTests.java
index 65b4390d6f..f357a3eb50 100644
--- a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/DatastoreTransactionManagerTests.java
+++ b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/DatastoreTransactionManagerTests.java
@@ -101,15 +101,15 @@ void testDoCommit() {
@Test
void testDoCommitFailure() {
-
+ DatastoreException exception = new DatastoreException(0, "", "");
when(this.transaction.isActive()).thenReturn(true);
- when(this.transaction.commit()).thenThrow(new DatastoreException(0, "", ""));
+ when(this.transaction.commit()).thenThrow(exception);
this.tx.setTransaction(this.transaction);
assertThatThrownBy(() -> this.manager.doCommit(this.status))
.isInstanceOf(TransactionSystemException.class)
- .hasMessage("Cloud Datastore transaction failed to commit.; "
- + "nested exception is com.google.cloud.datastore.DatastoreException: ");
+ .hasMessage("Cloud Datastore transaction failed to commit.")
+ .hasCause(exception);
}
@Test
@@ -130,15 +130,15 @@ void testDoRollback() {
@Test
void testDoRollbackFailure() {
-
+ DatastoreException exception = new DatastoreException(0, "", "");
when(this.transaction.isActive()).thenReturn(true);
- doThrow(new DatastoreException(0, "", "")).when(this.transaction).rollback();
+ doThrow(exception).when(this.transaction).rollback();
this.tx.setTransaction(this.transaction);
assertThatThrownBy(() -> this.manager.doRollback(this.status))
.isInstanceOf(TransactionSystemException.class)
- .hasMessage("Cloud Datastore transaction failed to rollback.; "
- + "nested exception is com.google.cloud.datastore.DatastoreException: ");
+ .hasMessage("Cloud Datastore transaction failed to rollback.")
+ .hasCause(exception);
}
@Test
diff --git a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/convert/DefaultDatastoreEntityConverterTests.java b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/convert/DefaultDatastoreEntityConverterTests.java
index 8a67579865..a6d14b2906 100644
--- a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/convert/DefaultDatastoreEntityConverterTests.java
+++ b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/convert/DefaultDatastoreEntityConverterTests.java
@@ -230,8 +230,8 @@ void testWrongTypeReadException() {
.isInstanceOf(DatastoreDataException.class)
.hasMessageContaining("Unable to read "
+ "com.google.cloud.spring.data.datastore.core.convert.TestDatastoreItem entity")
- .hasMessageContaining("Unable to read property boolField")
- .hasMessageContaining("Unable to convert class java.lang.Long to class java.lang.Boolean");
+ .hasStackTraceContaining("Unable to read property boolField")
+ .hasStackTraceContaining("Unable to convert class java.lang.Long to class java.lang.Boolean");
}
@Test
@@ -258,8 +258,8 @@ void testWrongTypeReadExceptionList() {
.isInstanceOf(DatastoreDataException.class)
.hasMessageContaining("Unable to read "
+ "com.google.cloud.spring.data.datastore.core.convert.TestDatastoreItem entity")
- .hasMessageContaining("Unable to read property boolField")
- .hasMessageContaining("Unable to convert class "
+ .hasStackTraceContaining("Unable to read property boolField")
+ .hasStackTraceContaining("Unable to convert class "
+ "com.google.common.collect.SingletonImmutableList to class java.lang.Boolean");
}
@@ -365,7 +365,7 @@ void testUnsupportedTypeWriteException() {
assertThatThrownBy(() -> ENTITY_CONVERTER.write(item, builder))
.isInstanceOf(DatastoreDataException.class)
.hasMessageContaining("Unable to write testItemUnsupportedFields.unsupportedField")
- .hasMessageContaining("Unable to convert class "
+ .hasStackTraceContaining("Unable to convert class "
+ "com.google.cloud.spring.data.datastore.core.convert."
+ "TestItemUnsupportedFields$NewType to Datastore supported type.");
}
@@ -402,7 +402,7 @@ void testUnsupportedTypeWrite() {
@Test
void testCollectionFieldsUnsupportedCollection() {
- ComparableBeanContextSupport comparableBeanContextSupport = new ComparableBeanContextSupport();
+ ComparableBeanContextSupport comparableBeanContextSupport = new ComparableBeanContextSupport<>();
comparableBeanContextSupport.add("this implementation of Collection");
comparableBeanContextSupport.add("is unsupported out of the box!");
@@ -423,10 +423,10 @@ void testCollectionFieldsUnsupportedCollection() {
.isInstanceOf(DatastoreDataException.class)
.hasMessageContaining("Unable to read"
+ " com.google.cloud.spring.data.datastore.core.convert.TestDatastoreItemCollections"
- + " entity;")
- .hasMessageContaining("Unable to read property beanContext;")
- .hasMessageContaining("Failed to convert from type [java.util.ArrayList>] to type"
- + " [com.google.cloud.spring.data.datastore.core.convert.TestDatastoreItemCollections$ComparableBeanContextSupport]");
+ + " entity")
+ .hasStackTraceContaining("Unable to read property beanContext")
+ .hasStackTraceContaining("Failed to convert from type [java.util.ImmutableCollections$ListN>] to type"
+ + " [com.google.cloud.spring.data.datastore.core.convert.TestDatastoreItemCollections$ComparableBeanContextSupport>]");
}
@Test
@@ -550,7 +550,7 @@ void testCollectionFieldsUnsupported() {
assertThatThrownBy(() -> ENTITY_CONVERTER.write(item, builder))
.isInstanceOf(DatastoreDataException.class)
.hasMessageContaining("Unable to write collectionOfUnsupportedTypes.unsupportedElts")
- .hasMessageContaining("Unable to convert "
+ .hasStackTraceContaining("Unable to convert "
+ "class com.google.cloud.spring.data.datastore.core.convert."
+ "TestItemUnsupportedFields$NewType to Datastore supported type.");
}
@@ -600,12 +600,12 @@ void testCollectionFieldsUnsupportedWriteReadException() {
Class parameter = TestItemUnsupportedFields.CollectionOfUnsupportedTypes.class;
assertThatThrownBy(() -> entityConverter.read(parameter, entity))
- .hasMessageContaining("Unable to read property unsupportedElts")
- .hasMessageContaining("Unable process elements of a collection")
- .hasMessageContaining("No converter found capable of converting from type [java.lang.Integer] "
+ .hasStackTraceContaining("Unable to read property unsupportedElts")
+ .hasStackTraceContaining("Unable process elements of a collection")
+ .hasStackTraceContaining("No converter found capable of converting from type [java.lang.Integer] "
+ "to type [com.google.cloud.spring.data.datastore.core.convert."
+ "TestItemUnsupportedFields$NewType]")
- .hasMessageContaining("Unable to read com.google.cloud.spring.data.datastore.core.convert."
+ .hasStackTraceContaining("Unable to read com.google.cloud.spring.data.datastore.core.convert."
+ "TestItemUnsupportedFields$CollectionOfUnsupportedTypes entity")
.isInstanceOf(DatastoreDataException.class);
}
@@ -882,7 +882,7 @@ void privateCustomMapExceptionTest() {
entityConverter.read(ServiceConfigurationPrivateCustomMap.class, entity);
})
.isInstanceOf(DatastoreDataException.class)
- .hasMessageContaining(
+ .hasStackTraceContaining(
"Unable to create an instance of a custom map type: "
+ "class com.google.cloud.spring.data.datastore.core.convert."
+ "DefaultDatastoreEntityConverterTests$PrivateCustomMap "
@@ -896,7 +896,7 @@ void testMismatchedStringIdLongProperty() {
assertThatThrownBy(() -> ENTITY_CONVERTER.read(LongIdEntity.class, testEntity))
.isInstanceOf(ConversionFailedException.class)
- .hasMessageContaining("The given key doesn't have a numeric ID but a conversion to Long was attempted");
+ .hasStackTraceContaining("The given key doesn't have a numeric ID but a conversion to Long was attempted");
}
@Test
@@ -906,7 +906,7 @@ void testMismatchedLongIdStringProperty() {
assertThatThrownBy(() -> ENTITY_CONVERTER.read(StringIdEntity.class, testEntity))
.isInstanceOf(ConversionFailedException.class)
- .hasMessageContaining("The given key doesn't have a String name value but a conversion to String was attempted");
+ .hasStackTraceContaining("The given key doesn't have a String name value but a conversion to String was attempted");
}
private Entity.Builder getEntityBuilder() {
diff --git a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/convert/EntityPropertyValueProviderTests.java b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/convert/EntityPropertyValueProviderTests.java
index ce57c28ee7..19c91d5cc8 100644
--- a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/convert/EntityPropertyValueProviderTests.java
+++ b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/convert/EntityPropertyValueProviderTests.java
@@ -127,8 +127,7 @@ void testException() {
assertThatThrownBy(() -> provider.getPropertyValue(testDpe))
.isInstanceOf(DatastoreDataException.class)
- .hasMessage("Unable to read property boolField; nested exception is "
- + "com.google.cloud.spring.data.datastore.core.mapping.DatastoreDataException: "
- + "Unable to convert class java.lang.Long to class java.lang.Boolean");
+ .hasMessageContaining("Unable to read property boolField")
+ .hasStackTraceContaining("Unable to convert class java.lang.Long to class java.lang.Boolean");
}
}
diff --git a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/convert/TestDatastoreItemCollections.java b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/convert/TestDatastoreItemCollections.java
index 4e8a609335..c627ed5e60 100644
--- a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/convert/TestDatastoreItemCollections.java
+++ b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/convert/TestDatastoreItemCollections.java
@@ -41,7 +41,7 @@ public class TestDatastoreItemCollections {
public TestDatastoreItemCollections(
List intList,
- ComparableBeanContextSupport beanContext,
+ ComparableBeanContextSupport beanContext,
String[] stringArray,
boolean[] boolArray,
byte[][] bytes,
@@ -133,7 +133,7 @@ private boolean equal(Object a, Object b) {
* BeanContextSupport does not provide an equals() implementation. This subclass overrides {@code
* equals/hashCode} and keeps a simple list of values to enable test verification.
*/
- static class ComparableBeanContextSupport extends BeanContextSupport {
+ static class ComparableBeanContextSupport extends BeanContextSupport {
private Set values = new HashSet<>();
@Override
diff --git a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/mapping/DatastoreMappingContextTests.java b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/mapping/DatastoreMappingContextTests.java
index 85cf212693..c8540b9294 100644
--- a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/mapping/DatastoreMappingContextTests.java
+++ b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/mapping/DatastoreMappingContextTests.java
@@ -25,7 +25,6 @@
import com.google.cloud.Timestamp;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
-import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
/** Tests for the `DatastoreMappingContext`. */
@@ -37,7 +36,7 @@ void testApplicationContextPassing() {
ApplicationContext applicationContext = mock(ApplicationContext.class);
context.setApplicationContext(applicationContext);
- context.createPersistentEntity(ClassTypeInformation.from(Object.class));
+ context.createPersistentEntity(TypeInformation.of(Object.class));
verify(mockEntity, times(1)).setApplicationContext(applicationContext);
}
@@ -47,7 +46,7 @@ void testApplicationContextIsNotSet() {
DatastorePersistentEntityImpl mockEntity = mock(DatastorePersistentEntityImpl.class);
DatastoreMappingContext context = createDatastoreMappingContextWith(mockEntity);
- context.createPersistentEntity(ClassTypeInformation.from(Object.class));
+ context.createPersistentEntity(TypeInformation.of(Object.class));
verifyNoMoreInteractions(mockEntity);
}
diff --git a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/mapping/DatastorePersistentEntityImplTests.java b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/mapping/DatastorePersistentEntityImplTests.java
index 2d17b21c9c..b1a20fd466 100644
--- a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/mapping/DatastorePersistentEntityImplTests.java
+++ b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/core/mapping/DatastorePersistentEntityImplTests.java
@@ -28,6 +28,7 @@
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.SimplePropertyHandler;
import org.springframework.data.util.ClassTypeInformation;
+import org.springframework.data.util.TypeInformation;
import org.springframework.expression.spel.SpelEvaluationException;
/** Tests for the Datastore Persistent Entity. */
@@ -38,7 +39,7 @@ class DatastorePersistentEntityImplTests {
@Test
void testTableName() {
DatastorePersistentEntityImpl entity =
- new DatastorePersistentEntityImpl<>(ClassTypeInformation.from(TestEntity.class), null);
+ new DatastorePersistentEntityImpl<>(TypeInformation.of(TestEntity.class), null);
assertThat(entity.kindName()).isEqualTo("custom_test_kind");
}
@@ -46,7 +47,7 @@ void testTableName() {
void testRawTableName() {
DatastorePersistentEntityImpl entity =
new DatastorePersistentEntityImpl<>(
- ClassTypeInformation.from(EntityNoCustomName.class), null);
+ TypeInformation.of(EntityNoCustomName.class), null);
assertThat(entity.kindName()).isEqualTo("entityNoCustomName");
}
@@ -55,7 +56,7 @@ void testRawTableName() {
void testEmptyCustomTableName() {
DatastorePersistentEntityImpl entity =
new DatastorePersistentEntityImpl<>(
- ClassTypeInformation.from(EntityEmptyCustomName.class), null);
+ TypeInformation.of(EntityEmptyCustomName.class), null);
assertThat(entity.kindName()).isEqualTo("entityEmptyCustomName");
}
@@ -64,9 +65,9 @@ void testEmptyCustomTableName() {
void testExpressionResolutionWithoutApplicationContext() {
DatastorePersistentEntityImpl entity =
new DatastorePersistentEntityImpl<>(
- ClassTypeInformation.from(EntityWithExpression.class), null);
+ TypeInformation.of(EntityWithExpression.class), null);
- assertThatThrownBy(() -> entity.kindName())
+ assertThatThrownBy(entity::kindName)
.isInstanceOf(SpelEvaluationException.class)
.hasMessageContaining("Property or field 'kindPostfix' cannot be found on null");
}
@@ -75,7 +76,7 @@ void testExpressionResolutionWithoutApplicationContext() {
void testExpressionResolutionFromApplicationContext() {
DatastorePersistentEntityImpl entity =
new DatastorePersistentEntityImpl<>(
- ClassTypeInformation.from(EntityWithExpression.class), null);
+ TypeInformation.of(EntityWithExpression.class), null);
ApplicationContext applicationContext = mock(ApplicationContext.class);
when(applicationContext.getBean("kindPostfix")).thenReturn("something");
@@ -103,7 +104,7 @@ void testGetIdPropertyOrFail() {
DatastorePersistentEntity testEntity = new DatastoreMappingContext().getPersistentEntity(EntityWithNoId.class);
- assertThatThrownBy(() -> testEntity.getIdPropertyOrFail())
+ assertThatThrownBy(testEntity::getIdPropertyOrFail)
.isInstanceOf(DatastoreDataException.class)
.hasMessage("An ID property was required but does not exist for the type: "
+ "class com.google.cloud.spring.data.datastore.core.mapping."
diff --git a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/repository/query/PartTreeDatastoreQueryTests.java b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/repository/query/PartTreeDatastoreQueryTests.java
index 29d18390b4..5bd326fc47 100644
--- a/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/repository/query/PartTreeDatastoreQueryTests.java
+++ b/spring-cloud-gcp-data-datastore/src/test/java/com/google/cloud/spring/data/datastore/repository/query/PartTreeDatastoreQueryTests.java
@@ -73,7 +73,7 @@
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
import org.springframework.data.repository.query.DefaultParameters;
-import org.springframework.data.util.ClassTypeInformation;
+import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
/** Tests for Part-Tree Datastore Query Methods. */
@@ -1062,7 +1062,7 @@ private void queryWithMockResult(
if (mockOptionalNullable) {
DefaultRepositoryMetadata mockMetadata = mock(DefaultRepositoryMetadata.class);
doReturn(m.getReturnType()).when(mockMetadata).getReturnedDomainClass(m);
- doReturn(ClassTypeInformation.fromReturnTypeOf(m)).when(mockMetadata).getReturnType(m);
+ doReturn(TypeInformation.fromReturnTypeOf(m)).when(mockMetadata).getReturnType(m);
DatastoreQueryMethod datastoreQueryMethod =
new DatastoreQueryMethod(m, mockMetadata, mock(SpelAwareProxyProjectionFactory.class));
doReturn(datastoreQueryMethod.isOptionalReturnType())
diff --git a/spring-cloud-gcp-data-firestore/pom.xml b/spring-cloud-gcp-data-firestore/pom.xml
index 32d55217b9..179a1437c5 100644
--- a/spring-cloud-gcp-data-firestore/pom.xml
+++ b/spring-cloud-gcp-data-firestore/pom.xml
@@ -7,7 +7,7 @@
spring-cloud-gcp
com.google.cloud
- 3.4.3-SNAPSHOT
+ 4.0.0-SNAPSHOT
spring-cloud-gcp-data-firestore
diff --git a/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/FirestoreTemplateTests.java b/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/FirestoreTemplateTests.java
index 448b653737..4e388b01ca 100644
--- a/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/FirestoreTemplateTests.java
+++ b/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/FirestoreTemplateTests.java
@@ -69,7 +69,7 @@ void setup() {
this.firestoreTemplate =
new FirestoreTemplate(
this.firestoreStub,
- this.parent,
+ parent,
new FirestoreDefaultClassMapper(mappingContext),
mappingContext);
}
@@ -91,7 +91,7 @@ void findAllTest() {
.build();
RunQueryRequest request =
RunQueryRequest.newBuilder()
- .setParent(this.parent)
+ .setParent(parent)
.setStructuredQuery(structuredQuery)
.build();
@@ -311,7 +311,7 @@ void findByIdTest() {
.verifyComplete();
GetDocumentRequest request =
- GetDocumentRequest.newBuilder().setName(this.parent + "/testEntities/" + "e1").build();
+ GetDocumentRequest.newBuilder().setName(parent + "/testEntities/" + "e1").build();
verify(this.firestoreStub, times(1)).getDocument(eq(request), any());
}
@@ -332,12 +332,12 @@ void findByIdErrorTest() {
.expectErrorMatches(
e ->
e instanceof FirestoreDataException
- && e.getMessage().contains("Firestore error")
+ && e.getCause().getMessage().contains("Firestore error")
&& e.getMessage().contains("Error while reading entries by id"))
.verify();
GetDocumentRequest request =
- GetDocumentRequest.newBuilder().setName(this.parent + "/testEntities/" + "e1").build();
+ GetDocumentRequest.newBuilder().setName(parent + "/testEntities/" + "e1").build();
verify(this.firestoreStub, times(1)).getDocument(eq(request), any());
}
@@ -360,7 +360,7 @@ void findByIdNotFoundTest() {
.verifyComplete();
GetDocumentRequest request =
- GetDocumentRequest.newBuilder().setName(this.parent + "/testEntities/" + "e1").build();
+ GetDocumentRequest.newBuilder().setName(parent + "/testEntities/" + "e1").build();
verify(this.firestoreStub, times(1)).getDocument(eq(request), any());
}
@@ -368,13 +368,13 @@ void findByIdNotFoundTest() {
@Test
void findAllByIdTest() {
GetDocumentRequest request1 =
- GetDocumentRequest.newBuilder().setName(this.parent + "/testEntities/e1").build();
+ GetDocumentRequest.newBuilder().setName(parent + "/testEntities/e1").build();
GetDocumentRequest request2 =
- GetDocumentRequest.newBuilder().setName(this.parent + "/testEntities/e2").build();
+ GetDocumentRequest.newBuilder().setName(parent + "/testEntities/e2").build();
GetDocumentRequest request3 =
- GetDocumentRequest.newBuilder().setName(this.parent + "/testEntities/e3").build();
+ GetDocumentRequest.newBuilder().setName(parent + "/testEntities/e3").build();
doAnswer(
invocation -> {
@@ -443,7 +443,7 @@ void countTest() {
.build();
RunQueryRequest request =
RunQueryRequest.newBuilder()
- .setParent(this.parent)
+ .setParent(parent)
.setStructuredQuery(structuredQuery)
.build();
@@ -479,7 +479,7 @@ void countWithQueryTest() {
RunQueryRequest request =
RunQueryRequest.newBuilder()
- .setParent(this.parent)
+ .setParent(parent)
.setStructuredQuery(expectedBuilder)
.build();
@@ -507,7 +507,7 @@ private void addWhere(StructuredQuery.Builder builder) {
void existsByIdTest() {
GetDocumentRequest request =
GetDocumentRequest.newBuilder()
- .setName(this.parent + "/testEntities/" + "e1")
+ .setName(parent + "/testEntities/" + "e1")
.setMask(DocumentMask.newBuilder().addFieldPaths("__name__").build())
.build();
@@ -535,7 +535,7 @@ void existsByIdTest() {
void existsByIdNotFoundTest() {
GetDocumentRequest request =
GetDocumentRequest.newBuilder()
- .setName(this.parent + "/testEntities/" + "e1")
+ .setName(parent + "/testEntities/" + "e1")
.setMask(DocumentMask.newBuilder().addFieldPaths("__name__").build())
.build();
@@ -579,7 +579,7 @@ void withParentTest_entityReference() {
GetDocumentRequest request =
GetDocumentRequest.newBuilder()
- .setName(this.parent + "/testEntities/parent/testEntities/child")
+ .setName(parent + "/testEntities/parent/testEntities/child")
.build();
verify(this.firestoreStub, times(1)).getDocument(eq(request), any());
@@ -605,7 +605,7 @@ void withParentTest_idClassReference() {
GetDocumentRequest request =
GetDocumentRequest.newBuilder()
- .setName(this.parent + "/testEntities/parent/testEntities/child")
+ .setName(parent + "/testEntities/parent/testEntities/child")
.build();
verify(this.firestoreStub, times(1)).getDocument(eq(request), any());
@@ -704,7 +704,7 @@ public int hashCode() {
}
@Document(collectionName = "testEntities")
- class TestEntityUpdateTimeVersion {
+ static class TestEntityUpdateTimeVersion {
@DocumentId public String id;
@UpdateTime(version = true)
@@ -724,12 +724,10 @@ public boolean equals(Object o) {
if (this == o) {
return true;
}
- if (!(o instanceof TestEntityUpdateTimeVersion)) {
+ if (!(o instanceof TestEntityUpdateTimeVersion that)) {
return false;
}
- TestEntityUpdateTimeVersion that = (TestEntityUpdateTimeVersion) o;
-
if (!Objects.equals(id, that.id)) {
return false;
}
@@ -745,7 +743,7 @@ public int hashCode() {
}
@Document(collectionName = "testEntities")
- class TestEntityUpdateTime {
+ static class TestEntityUpdateTime {
@DocumentId public String id;
@UpdateTime public Timestamp updateTime;
@@ -764,12 +762,10 @@ public boolean equals(Object o) {
if (this == o) {
return true;
}
- if (!(o instanceof TestEntityUpdateTime)) {
+ if (!(o instanceof TestEntityUpdateTime that)) {
return false;
}
- TestEntityUpdateTime that = (TestEntityUpdateTime) o;
-
if (!Objects.equals(id, that.id)) {
return false;
}
diff --git a/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/mapping/FirestorePersistentEntityImplTests.java b/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/mapping/FirestorePersistentEntityImplTests.java
index 53e3daef4c..1ea8d1b49f 100644
--- a/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/mapping/FirestorePersistentEntityImplTests.java
+++ b/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/mapping/FirestorePersistentEntityImplTests.java
@@ -20,7 +20,7 @@
import com.google.cloud.spring.data.firestore.Document;
import org.junit.jupiter.api.Test;
-import org.springframework.data.util.ClassTypeInformation;
+import org.springframework.data.util.TypeInformation;
/** Tests for {@link FirestorePersistentEntityImpl}. */
class FirestorePersistentEntityImplTests {
@@ -28,14 +28,14 @@ class FirestorePersistentEntityImplTests {
@Test
void testSetCollectionName() {
FirestorePersistentEntity firestorePersistentEntity =
- new FirestorePersistentEntityImpl<>(ClassTypeInformation.from(Student.class));
+ new FirestorePersistentEntityImpl<>(TypeInformation.of(Student.class));
assertThat(firestorePersistentEntity.collectionName()).isEqualTo("student");
}
@Test
void testInferCollectionName() {
FirestorePersistentEntity firestorePersistentEntity =
- new FirestorePersistentEntityImpl<>(ClassTypeInformation.from(Employee.class));
+ new FirestorePersistentEntityImpl<>(TypeInformation.of(Employee.class));
assertThat(firestorePersistentEntity.collectionName()).isEqualTo("employee_table");
}
diff --git a/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/mapping/FirestorePersistentPropertyImplTest.java b/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/mapping/FirestorePersistentPropertyImplTest.java
index 9de04f9dde..e45f52b307 100644
--- a/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/mapping/FirestorePersistentPropertyImplTest.java
+++ b/spring-cloud-gcp-data-firestore/src/test/java/com/google/cloud/spring/data/firestore/mapping/FirestorePersistentPropertyImplTest.java
@@ -28,7 +28,7 @@
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
-import org.springframework.data.util.ClassTypeInformation;
+import org.springframework.data.util.TypeInformation;
import org.springframework.test.context.junit.jupiter.SpringExtension;
/** Tests for {@link FirestorePersistentPropertyImpl}. */
@@ -46,7 +46,7 @@ void testGetFieldName_isIdProperty() throws NoSuchFieldException {
when(mockProperty.getName()).thenReturn("id");
when(mockProperty.getField()).thenReturn(Optional.of(TestEntity.class.getField("id")));
when(mockPersistentEntity.getTypeInformation())
- .thenReturn(ClassTypeInformation.from(TestEntity.class));
+ .thenReturn(TypeInformation.of(TestEntity.class));
when(mockPersistentEntity.getType()).thenReturn(TestEntity.class);
FirestorePersistentPropertyImpl firestorePersistentProperty =
diff --git a/spring-cloud-gcp-data-spanner/pom.xml b/spring-cloud-gcp-data-spanner/pom.xml
index d2773fc5f7..a02c377b45 100644
--- a/spring-cloud-gcp-data-spanner/pom.xml
+++ b/spring-cloud-gcp-data-spanner/pom.xml
@@ -7,9 +7,8 @@
spring-cloud-gcp
com.google.cloud
- 3.4.3-SNAPSHOT
+ 4.0.0-SNAPSHOT
- com.google.cloud
spring-cloud-gcp-data-spanner
Spring Framework on Google Cloud Module - Cloud Spanner
Spring Framework on Google Cloud Cloud Spanner Module
diff --git a/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityReader.java b/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityReader.java
index c171bf6988..ed42f46fd4 100644
--- a/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityReader.java
+++ b/spring-cloud-gcp-data-spanner/src/main/java/com/google/cloud/spring/data/spanner/core/convert/ConverterAwareMappingSpannerEntityReader.java
@@ -22,8 +22,8 @@
import com.google.cloud.spring.data.spanner.core.mapping.SpannerPersistentEntity;
import com.google.cloud.spring.data.spanner.core.mapping.SpannerPersistentProperty;
import java.util.Set;
+import org.springframework.data.mapping.InstanceCreatorMetadata;
import org.springframework.data.mapping.PersistentPropertyAccessor;
-import org.springframework.data.mapping.PreferredConstructor;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.model.EntityInstantiator;
import org.springframework.data.mapping.model.EntityInstantiators;
@@ -39,9 +39,9 @@ class ConverterAwareMappingSpannerEntityReader implements SpannerEntityReader {
private final SpannerMappingContext spannerMappingContext;
- private EntityInstantiators instantiators;
+ private final EntityInstantiators instantiators;
- private SpannerReadConverter converter;
+ private final SpannerReadConverter converter;
ConverterAwareMappingSpannerEntityReader(
SpannerMappingContext spannerMappingContext, SpannerReadConverter spannerReadConverter) {
@@ -75,8 +75,8 @@ public R read(
StructPropertyValueProvider propertyValueProvider =
new StructPropertyValueProvider(structAccessor, this.converter, this, allowMissingColumns);
- PreferredConstructor, SpannerPersistentProperty> persistenceConstructor =
- persistentEntity.getPersistenceConstructor();
+ InstanceCreatorMetadata instanceCreatorMetadata =
+ persistentEntity.getInstanceCreatorMetadata();
// @formatter:off
ParameterValueProvider parameterValueProvider =
@@ -105,7 +105,7 @@ public R read(
includeColumns,
readAllColumns,
allowMissingColumns,
- persistenceConstructor)) {
+ instanceCreatorMetadata)) {
Object value = propertyValueProvider.getPropertyValue(spannerPersistentProperty);
accessor.setProperty(spannerPersistentProperty, value);
@@ -122,7 +122,7 @@ private boolean shouldSkipProperty(
Set includeColumns,
boolean readAllColumns,
boolean allowMissingColumns,
- PreferredConstructor, SpannerPersistentProperty> persistenceConstructor) {
+ InstanceCreatorMetadata