Skip to content

Commit

Permalink
Remove spring managed dependency with version consideration (#602)
Browse files Browse the repository at this point in the history
  • Loading branch information
ravig-kant authored and fabapp2 committed Jan 31, 2023
1 parent 2713377 commit f47e540
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@

import io.micrometer.core.lang.Nullable;
import lombok.*;
import org.openrewrite.semver.LatestRelease;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

@Getter
Expand Down Expand Up @@ -66,6 +68,15 @@ public String toString() {
"</dependency>";
}

public boolean isRecentThen(Dependency that){
return this.equals(that) && comparator().compare(this, that) >= 0;
}

private Comparator<Dependency> comparator(){
LatestRelease latestRelease = new LatestRelease(null);
return Comparator.comparing(Dependency::getVersion, latestRelease::compare);
}

private String exclusionString() {
if (exclusions.isEmpty()) {
return "";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.springframework.sbm.build.api;

import org.openrewrite.maven.internal.MavenPomDownloader;
import org.openrewrite.maven.tree.GroupArtifactVersion;
import org.openrewrite.maven.tree.MavenRepository;
import org.springframework.sbm.openrewrite.RewriteExecutionContext;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

/**
* This class holds all the dependencies included in a spring artifact
*/
public class SpringManagedDependencies {

private static List<MavenRepository> SPRING_REPOSITORIES = List.of(
new MavenRepository("spring-release", "https://repo.spring.io/release", true, false, null, null)
);

private List<org.openrewrite.maven.tree.Dependency> dependencies;
private static Map<GroupArtifactVersion, SpringManagedDependencies> INSTANCES = new HashMap<>();

public static SpringManagedDependencies by(String groupId, String artifact, String version){
final GroupArtifactVersion groupArtifactVersion =
new GroupArtifactVersion(groupId, artifact, version);

INSTANCES.computeIfAbsent(groupArtifactVersion, SpringManagedDependencies::new);
return INSTANCES.get(groupArtifactVersion);
}

private SpringManagedDependencies(GroupArtifactVersion groupArtifactVersion){
dependencies = new MavenPomDownloader(Collections.emptyMap(), new RewriteExecutionContext())
.download(groupArtifactVersion, null, null, SPRING_REPOSITORIES)
.getDependencies();
}

public Stream<Dependency> stream(){
return dependencies.stream()
.map(d -> Dependency.builder()
.groupId(d.getGroupId())
.artifactId(d.getArtifactId())
.version(d.getVersion())
.build()
);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.springframework.sbm.build.migration.actions;

import org.springframework.sbm.build.api.Dependency;
import org.springframework.sbm.build.api.SpringManagedDependencies;
import org.springframework.sbm.engine.context.ProjectContext;
import org.springframework.sbm.engine.recipe.AbstractAction;

import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static org.openrewrite.maven.tree.Scope.Compile;

/**
* The action removes the dependencies directly managed by Spring from the project dependencies
* Add this action at the end of recipe so that any spring artifact inclusions as part of the
* other actions are also included while removing the dependencies.
*/
public class RemoveManagedDependencies extends AbstractAction {

@Override
public void apply(ProjectContext context) {
//FIXME handle multi-module projects
final List<Dependency> springManagedDependencies = context.getBuildFile()
.getDeclaredDependencies(Compile)
.stream()
.filter(this::isSpringFrameworkDependency)
.map(d -> SpringManagedDependencies.by(d.getGroupId(),d.getArtifactId(),d.getVersion()))
.flatMap(SpringManagedDependencies::stream)
.distinct()
.collect(Collectors.toList());

Predicate<Dependency> isAlreadyManagedBySpring = d -> springManagedDependencies
.stream()
.filter(d::equals)
.anyMatch(s -> s.isRecentThen(d));

final List<Dependency> dependenciesToBeRemoved = context.getBuildFile()
.getDeclaredDependencies(Compile)
.stream()
.filter(isAlreadyManagedBySpring)
.collect(Collectors.toList());

RemoveDependencies removeDependenciesAction = new RemoveDependencies();
removeDependenciesAction.setDependencies(dependenciesToBeRemoved);
removeDependenciesAction.apply(context);
}

private boolean isSpringFrameworkDependency(Dependency dependency){
return dependency.getGroupId().startsWith("org.springframework");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.springframework.sbm.build.api;

import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

public class SpringManagedDependenciesTest {

@Test
public void pullBootStarter274Dependencies_expectJakartaAnnotationDependency(){
String jakartaCoordinates = "jakarta.annotation:jakarta.annotation-api:1.3.5";

assertThat( SpringManagedDependencies.by("org.springframework.boot", "spring-boot-starter", "2.7.4")
.stream()
.map(Dependency::getCoordinates)
.anyMatch(jakartaCoordinates::equals)
).isTrue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.springframework.sbm.build.migration.actions;

import org.junit.jupiter.api.Test;
import org.openrewrite.semver.LatestRelease;
import org.springframework.sbm.build.api.Dependency;
import org.springframework.sbm.engine.context.ProjectContext;
import org.springframework.sbm.project.resource.TestProjectContext;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

public class RemoveManagedDependenciesTest {

@Test
public void givenProjectWithManagedDependency_removeSpringManagedDependencies_expectHibernateDependencyRemoved(){

LatestRelease latestRelease = new LatestRelease(null);
System.out.println(latestRelease.compare(null, "5.6.11.Final", "5.6.11.Final"));

final String hibernateCoordinates = "org.hibernate:hibernate-core:5.6.11.Final";
final String springBootDataJpaCoordinates = "org.springframework.boot:spring-boot-starter-data-jpa:2.7.4";

final ProjectContext projectContext = TestProjectContext.buildProjectContext()
.withBuildFileHavingDependencies(hibernateCoordinates, springBootDataJpaCoordinates)
.build();

RemoveManagedDependencies removeManagedDependencies = new RemoveManagedDependencies();
removeManagedDependencies.apply(projectContext);

assertThat(projectContext.getBuildFile()
.getDeclaredDependencies()
.stream()
.map(Dependency::getCoordinates)
.anyMatch(hibernateCoordinates::equals)
).isFalse();
}

@Test
public void givenProjectWithLowerVersionedManagedDependency_removeSpringManagedDependencies_expectDependencyRemoved(){
final String hibernateCoordinates = "org.hibernate:hibernate-core:5.3.2.Final";
final String springBootDataJpaCoordinates = "org.springframework.boot:spring-boot-starter-data-jpa:2.7.4";

final ProjectContext projectContext = TestProjectContext.buildProjectContext()
.withBuildFileHavingDependencies(hibernateCoordinates, springBootDataJpaCoordinates)
.build();

RemoveManagedDependencies removeManagedDependencies = new RemoveManagedDependencies();
removeManagedDependencies.apply(projectContext);

assertThat(projectContext.getBuildFile()
.getDeclaredDependencies()
.stream()
.map(Dependency::getCoordinates)
.anyMatch(hibernateCoordinates::equals)
).isFalse();
}

@Test
public void givenProjectWithHigherVersionedManagedDependency_removeSpringManagedDependencies_expectDependencyRemoved(){
final String hibernateCoordinates = "org.hibernate:hibernate-core:5.12.2.Final";
final String springBootDataJpaCoordinates = "org.springframework.boot:spring-boot-starter-data-jpa:2.7.4";

final ProjectContext projectContext = TestProjectContext.buildProjectContext()
.withBuildFileHavingDependencies(hibernateCoordinates, springBootDataJpaCoordinates)
.build();

RemoveManagedDependencies removeManagedDependencies = new RemoveManagedDependencies();
removeManagedDependencies.apply(projectContext);

assertThat(projectContext.getBuildFile()
.getDeclaredDependencies()
.stream()
.map(Dependency::getCoordinates)
.anyMatch(hibernateCoordinates::equals)
).isTrue();
}
}

0 comments on commit f47e540

Please sign in to comment.