Break cycle in spring-boot-data-* modules
There was a cycle in the spring-boot-data-* modules. SpringDataWebAutoConfiguration (which sits at the spring-data-commons level) referenced RepositoryRestMvcAutoConfiguration (which sits at the spring-data-rest level). This dependency's expressed in the wrong direction as data-rest depends on data-commons. The resulting cycle was not noticable as it was expressed through a String afterName attribute on `@AutoConfiguration`. spring-boot-data-commons was also using spring-boot-data-jpa for its tests, which also results in an inverted dependency relationship. This commit reworks things so that all of the spring-boot-data-* modules depend upon spring-boot-data-commons, mirroring the dependency relationship in Spring Data. The integration tests in spring-boot-data-commons have been reworked to use Spring Data directly, avoiding the need for a circular from spring-boot-data-commons to another spring-boot-data-* module. See gh-46071
This commit is contained in:
parent
905964ff78
commit
c474f24fe8
|
@ -28,6 +28,7 @@ description = "Spring Boot Data Cassandra"
|
|||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot-cassandra"))
|
||||
api(project(":spring-boot-project:spring-boot-data-commons"))
|
||||
api("org.springframework.data:spring-data-cassandra") {
|
||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||
}
|
||||
|
|
|
@ -30,13 +30,13 @@ dependencies {
|
|||
api("org.springframework.data:spring-data-commons")
|
||||
|
||||
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
|
||||
optional(project(":spring-boot-project:spring-boot-data-rest"))
|
||||
optional(project(":spring-boot-project:spring-boot-metrics"))
|
||||
|
||||
testImplementation(project(":spring-boot-project:spring-boot-data-jpa"))
|
||||
testImplementation(project(":spring-boot-project:spring-boot-jdbc"))
|
||||
testImplementation(project(":spring-boot-project:spring-boot-test"))
|
||||
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
||||
testImplementation(testFixtures(project(":spring-boot-project:spring-boot-autoconfigure")))
|
||||
testImplementation("org.springframework.data:spring-data-jdbc")
|
||||
|
||||
testRuntimeOnly("ch.qos.logback:logback-classic")
|
||||
testRuntimeOnly("com.h2database:h2")
|
||||
|
|
|
@ -50,7 +50,7 @@ public class MetricsRepositoryMethodInvocationListener implements RepositoryMeth
|
|||
* @param tagsProvider provider for metrics tags
|
||||
* @param metricName name of the metric to record
|
||||
* @param autoTimer the auto-timers to apply or {@code null} to disable auto-timing
|
||||
* @since 2.5.4
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public MetricsRepositoryMethodInvocationListener(Supplier<MeterRegistry> registrySupplier,
|
||||
RepositoryTagsProvider tagsProvider, String metricName, AutoTimer autoTimer) {
|
||||
|
|
|
@ -45,7 +45,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|||
* @author Yanming Zhou
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@AutoConfiguration(afterName = "org.springframework.boot.data.rest.autoconfigure.RepositoryRestMvcAutoConfiguration")
|
||||
@AutoConfiguration
|
||||
@EnableSpringDataWebSupport
|
||||
@ConditionalOnWebApplication(type = Type.SERVLET)
|
||||
@ConditionalOnClass({ PageableHandlerMethodArgumentResolver.class, WebMvcConfigurer.class })
|
||||
|
|
|
@ -14,39 +14,19 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.data.metrics.autoconfigure.city;
|
||||
package org.springframework.boot.data.domain.city;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class City implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
public class City {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String state;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String country;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String map;
|
||||
|
||||
protected City() {
|
||||
}
|
||||
|
||||
public City(String name, String country) {
|
||||
this.name = name;
|
||||
this.country = country;
|
||||
|
@ -56,21 +36,13 @@ public class City implements Serializable {
|
|||
return this.name;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return this.country;
|
||||
}
|
||||
|
||||
public String getMap() {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName() + "," + getState() + "," + getCountry();
|
||||
return getName() + "," + getCountry();
|
||||
}
|
||||
|
||||
}
|
|
@ -14,19 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.data.metrics.autoconfigure.city;
|
||||
package org.springframework.boot.data.domain.city;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
public interface CityRepository extends JpaRepository<City, Long> {
|
||||
|
||||
@Override
|
||||
Page<City> findAll(Pageable pageable);
|
||||
|
||||
Page<City> findByNameLikeAndCountryLikeAllIgnoringCase(String name, String country, Pageable pageable);
|
||||
|
||||
City findByNameAndCountryAllIgnoringCase(String name, String country);
|
||||
public interface CityRepository extends CrudRepository<City, Long> {
|
||||
|
||||
}
|
|
@ -22,16 +22,20 @@ import io.micrometer.core.instrument.binder.MeterBinder;
|
|||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.data.jpa.autoconfigure.JpaRepositoriesAutoConfiguration;
|
||||
import org.springframework.boot.data.metrics.autoconfigure.city.CityRepository;
|
||||
import org.springframework.boot.jdbc.autoconfigure.EmbeddedDataSourceConfiguration;
|
||||
import org.springframework.boot.jpa.autoconfigure.hibernate.HibernateJpaAutoConfiguration;
|
||||
import org.springframework.boot.data.domain.city.City;
|
||||
import org.springframework.boot.data.domain.city.CityRepository;
|
||||
import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.jdbc.autoconfigure.DataSourceInitializationAutoConfiguration;
|
||||
import org.springframework.boot.jdbc.autoconfigure.DataSourceTransactionManagerAutoConfiguration;
|
||||
import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration;
|
||||
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
@ -40,14 +44,22 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@WithResource(name = "schema.sql", content = """
|
||||
CREATE TABLE CITY (
|
||||
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
name VARCHAR(30),
|
||||
country VARCHAR(30)
|
||||
);
|
||||
""")
|
||||
class RepositoryMetricsAutoConfigurationIntegrationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withBean(SimpleMeterRegistry.class)
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(HibernateJpaAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, RepositoryMetricsAutoConfiguration.class))
|
||||
.withUserConfiguration(EmbeddedDataSourceConfiguration.class, TestConfig.class);
|
||||
.withConfiguration(AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class,
|
||||
RepositoryMetricsAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
|
||||
DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class,
|
||||
DataSourceInitializationAutoConfiguration.class))
|
||||
.withUserConfiguration(TestConfig.class);
|
||||
|
||||
@Test
|
||||
void repositoryMethodCallRecordsMetrics() {
|
||||
|
@ -68,8 +80,8 @@ class RepositoryMetricsAutoConfigurationIntegrationTests {
|
|||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfigurationPackage
|
||||
static class TestConfig {
|
||||
@EnableJdbcRepositories(basePackageClasses = City.class)
|
||||
static class TestConfig extends AbstractJdbcConfiguration {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-present 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 org.springframework.boot.data.web.autoconfigure.domain.city;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class City implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String state;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String country;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String map;
|
||||
|
||||
protected City() {
|
||||
}
|
||||
|
||||
public City(String name, String country) {
|
||||
this.name = name;
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return this.country;
|
||||
}
|
||||
|
||||
public String getMap() {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName() + "," + getState() + "," + getCountry();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-present 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 org.springframework.boot.data.web.autoconfigure.domain.city;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface CityRepository extends JpaRepository<City, Long> {
|
||||
|
||||
@Override
|
||||
Page<City> findAll(Pageable pageable);
|
||||
|
||||
Page<City> findByNameLikeAndCountryLikeAllIgnoringCase(String name, String country, Pageable pageable);
|
||||
|
||||
City findByNameAndCountryAllIgnoringCase(String name, String country);
|
||||
|
||||
}
|
|
@ -27,6 +27,7 @@ description = "Spring Boot Data Couchbase"
|
|||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot-couchbase"))
|
||||
api(project(":spring-boot-project:spring-boot-data-commons"))
|
||||
api("org.springframework.data:spring-data-couchbase")
|
||||
|
||||
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
|
||||
|
|
|
@ -27,6 +27,7 @@ plugins {
|
|||
description = "Spring Boot Data Elasticsearch"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot-data-commons"))
|
||||
api(project(":spring-boot-project:spring-boot-elasticsearch"))
|
||||
api("org.springframework.data:spring-data-elasticsearch")
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ plugins {
|
|||
description = "Spring Boot Data JDBC"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot-data-commons"))
|
||||
api(project(":spring-boot-project:spring-boot-jdbc"))
|
||||
api("org.springframework.data:spring-data-jdbc")
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ plugins {
|
|||
description = "Spring Boot Data JPA"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot-data-commons"))
|
||||
api(project(":spring-boot-project:spring-boot-jpa"))
|
||||
api("org.springframework.data:spring-data-jpa")
|
||||
api("org.springframework:spring-aspects")
|
||||
|
@ -46,4 +47,5 @@ dependencies {
|
|||
testRuntimeOnly("ch.qos.logback:logback-classic")
|
||||
testRuntimeOnly("com.h2database:h2")
|
||||
testRuntimeOnly("com.zaxxer:HikariCP")
|
||||
testRuntimeOnly("jakarta.servlet:jakarta.servlet-api")
|
||||
}
|
||||
|
|
|
@ -14,15 +14,15 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.data.web.autoconfigure;
|
||||
package org.springframework.boot.data.jpa.autoconfigure;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
|
||||
import org.springframework.boot.data.jpa.autoconfigure.JpaRepositoriesAutoConfiguration;
|
||||
import org.springframework.boot.data.web.autoconfigure.domain.city.City;
|
||||
import org.springframework.boot.data.web.autoconfigure.domain.city.CityRepository;
|
||||
import org.springframework.boot.data.jpa.autoconfigure.domain.city.City;
|
||||
import org.springframework.boot.data.jpa.autoconfigure.domain.city.CityRepository;
|
||||
import org.springframework.boot.data.web.autoconfigure.SpringDataWebAutoConfiguration;
|
||||
import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.jpa.autoconfigure.hibernate.HibernateJpaAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
|
@ -42,7 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class SpringDataWebAutoConfigurationJpaTests {
|
||||
class JpaRepositoriesSpringDataWebAutoConfigurationTests {
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
|
|
@ -26,6 +26,7 @@ plugins {
|
|||
description = "Spring Boot Data LDAP"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot-data-commons"))
|
||||
api(project(":spring-boot-project:spring-boot-ldap"))
|
||||
api("org.springframework.data:spring-data-ldap")
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ description = "Spring Boot Data MongoDB"
|
|||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot"))
|
||||
api(project(":spring-boot-project:spring-boot-data-commons"))
|
||||
api(project(":spring-boot-project:spring-boot-mongodb"))
|
||||
api("org.springframework.data:spring-data-mongodb")
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ plugins {
|
|||
description = "Spring Boot Data Neo4j"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot-data-commons"))
|
||||
api(project(":spring-boot-project:spring-boot-neo4j"))
|
||||
api(project(":spring-boot-project:spring-boot-tx"))
|
||||
api("org.springframework.data:spring-data-neo4j")
|
||||
|
|
|
@ -27,6 +27,7 @@ plugins {
|
|||
description = "Spring Boot Data R2DBC"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot-data-commons"))
|
||||
api(project(":spring-boot-project:spring-boot-r2dbc"))
|
||||
api("io.r2dbc:r2dbc-spi")
|
||||
api("io.r2dbc:r2dbc-pool")
|
||||
|
|
|
@ -28,6 +28,7 @@ description = "Spring Boot Data Redis"
|
|||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot"))
|
||||
api(project(":spring-boot-project:spring-boot-data-commons"))
|
||||
api("io.lettuce:lettuce-core")
|
||||
api("org.springframework.data:spring-data-redis")
|
||||
|
||||
|
|
|
@ -26,8 +26,9 @@ plugins {
|
|||
description = "Spring Boot Data REST"
|
||||
|
||||
dependencies {
|
||||
api(project(":spring-boot-project:spring-boot-webmvc"))
|
||||
api(project(":spring-boot-project:spring-boot-data-commons"))
|
||||
api(project(":spring-boot-project:spring-boot-jackson"))
|
||||
api(project(":spring-boot-project:spring-boot-webmvc"))
|
||||
api("org.springframework.data:spring-data-rest-webmvc")
|
||||
|
||||
optional(project(":spring-boot-project:spring-boot-autoconfigure"))
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.data.web.autoconfigure.SpringDataWebAutoConfiguration;
|
||||
import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
@ -46,7 +47,7 @@ import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
|||
* @author Andy Wilkinson
|
||||
* @since 4.0.0
|
||||
*/
|
||||
@AutoConfiguration(after = JacksonAutoConfiguration.class)
|
||||
@AutoConfiguration(before = SpringDataWebAutoConfiguration.class, after = JacksonAutoConfiguration.class)
|
||||
@ConditionalOnWebApplication(type = Type.SERVLET)
|
||||
@ConditionalOnMissingBean(RepositoryRestMvcConfiguration.class)
|
||||
@ConditionalOnClass(RepositoryRestMvcConfiguration.class)
|
||||
|
|
Loading…
Reference in New Issue