#1119 - Avoid reference to spring-webmvc in configuration for RestTemplate.
RestTemplateHateoasConfiguration previously referred to HypermediaWebMvcConfigurer which is turn depending on WebMvcConfigurer, a type living in spring-webmvc. The very former would still get active in WebFlux as the web stack is selected based on the presence of either DispatcherServlet or DispatcherHandler. This is now resolved by using a WebMvcConverter indrection to handle the configuration tweaks avoiding the reference to interfaces from spring-webmvc. Introduced an ArchUnit based test that Spring HATEOAS code only depends on Spring types containing references to reactive types from either the ….reactive package or classes starting with WebFlux.
This commit is contained in:
@@ -15,25 +15,36 @@
|
||||
*/
|
||||
package org.springframework.hateoas;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.*;
|
||||
import static org.springframework.hateoas.ArchitectureTest.Architecture.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import com.tngtech.archunit.base.DescribedPredicate;
|
||||
import com.tngtech.archunit.core.domain.Dependency;
|
||||
import com.tngtech.archunit.core.domain.JavaClass;
|
||||
import com.tngtech.archunit.core.domain.JavaClasses;
|
||||
import com.tngtech.archunit.core.importer.ClassFileImporter;
|
||||
import com.tngtech.archunit.core.importer.ImportOption;
|
||||
import com.tngtech.archunit.core.importer.ImportOptions;
|
||||
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
|
||||
import com.tngtech.archunit.library.dependencies.SliceRule;
|
||||
import com.tngtech.archunit.library.dependencies.SlicesRuleDefinition;
|
||||
|
||||
/**
|
||||
* Tests to verify certain architectural assumptions.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Oliver Drotbohm
|
||||
*/
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
class ArchitectureTest {
|
||||
|
||||
ImportOptions options = new ImportOptions().with(ImportOption.Predefined.DONT_INCLUDE_TESTS);
|
||||
JavaClasses classes = new ClassFileImporter(options) //
|
||||
.importPackages("org.springframework.hateoas");
|
||||
.importPackages("org.springframework.hateoas", "org.springframework");
|
||||
|
||||
@Test
|
||||
void assertNoCyclicPackageDependencies() {
|
||||
@@ -44,4 +55,58 @@ class ArchitectureTest {
|
||||
|
||||
rule.check(classes);
|
||||
}
|
||||
|
||||
@Test // #1119
|
||||
void onlyReactivePackagesReferToReactiveTypesInSpringFramework() {
|
||||
|
||||
DescribedPredicate<JavaClass> areSpringFrameworkClassesWithReactiveDependency = JavaClass.Predicates
|
||||
.resideInAnyPackage("org.springframework..") //
|
||||
.and(JavaClass.Predicates.resideOutsideOfPackage("..hateoas..")) //
|
||||
.and(dependsOn(reactiveType()));
|
||||
|
||||
ArchRuleDefinition.noClasses().that() //
|
||||
.resideInAnyPackage("org.springframework.hateoas..") //
|
||||
.and().resideOutsideOfPackages("..reactive") //
|
||||
.and().haveSimpleNameNotStartingWith("WebFlux") //
|
||||
.and().haveSimpleNameNotStartingWith("WebClient") //
|
||||
.should().dependOnClassesThat(areSpringFrameworkClassesWithReactiveDependency) //
|
||||
.check(classes);
|
||||
}
|
||||
|
||||
static class Architecture {
|
||||
|
||||
public static DescribedPredicate<JavaClass> hasWebFluxPrefix() {
|
||||
return simpleNameStartingWith("WebClient").or(simpleNameStartingWith("WebFlux"));
|
||||
}
|
||||
|
||||
public static DescribedPredicate<JavaClass> reactorType() {
|
||||
return resideInAPackage("reactor..");
|
||||
}
|
||||
|
||||
public static DescribedPredicate<JavaClass> reactiveStreamsType() {
|
||||
return resideInAPackage("org.reactivestreams..");
|
||||
}
|
||||
|
||||
public static DescribedPredicate<JavaClass> reactiveType() {
|
||||
return reactorType().or(reactiveStreamsType());
|
||||
}
|
||||
|
||||
public static DescribedPredicate<JavaClass> dependsOn(DescribedPredicate<JavaClass> predicate) {
|
||||
|
||||
return new DescribedPredicate<JavaClass>("depends on reactive types") {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see com.tngtech.archunit.base.DescribedPredicate#apply(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean apply(@Nullable JavaClass input) {
|
||||
|
||||
return input != null && input.getDirectDependenciesFromSelf().stream() //
|
||||
.map(Dependency::getTargetClass) //
|
||||
.anyMatch(predicate::apply);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user