Skip to content

Commit

Permalink
feat: Add support for using Spring Beans as Java based migrations. (#…
Browse files Browse the repository at this point in the history
…1395)

Closes #1393.
  • Loading branch information
michael-simons authored Jul 26, 2024
1 parent a131d86 commit 4dce778
Show file tree
Hide file tree
Showing 34 changed files with 316 additions and 89 deletions.
4 changes: 3 additions & 1 deletion docs/modules/ROOT/pages/usage.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,9 @@ The driver is managed by Spring Boot since 2.4, and you can enjoy configuration
For Spring Boot versions prior to Spring Boot 2.4, please have a look at version https://github.com/michael-simons/neo4j-migrations/tree/0.0.13[0.0.13] of this library.

Neo4j-Migrations will automatically look for migrations in `classpath:neo4j/migrations` and will fail if this location does not exist.
It does not scan by default for Java-based migrations.
It does not scan by default for Java-based migrations itself.
It will however discover all Java-based migrations that are annotated with `@Component`, `@Service` or other stereotypes and all beans that made it otherwise into the application context.
Such a Java-based migrations is free to use anything that is injectable itself, such as Spring Data Neo4j repositories.

Here's an example on how to configure the driver and the migrations:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-annotation-processing</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-annotation-catalog</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion extensions/neo4j-migrations-annotation-processing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-annotation-processing</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-annotation-processor-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-annotation-processing</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-annotation-processor</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion extensions/neo4j-migrations-formats-adoc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion extensions/neo4j-migrations-formats-csv/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion extensions/neo4j-migrations-formats-markdown/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion neo4j-migrations-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-bom</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion neo4j-migrations-cli/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-cli</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion neo4j-migrations-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-examples</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-cluster-tests</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-examples</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-examples-sb-testharness</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-examples</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-examples-sb</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2020-2024 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 ac.simons.neo4j.migrations.examples.sb;

import org.springframework.data.neo4j.repository.Neo4jRepository;

/**
* Just for demo purposes.
*/
public interface PersonRepository extends Neo4jRepository<Person, String> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2020-2024 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 ac.simons.neo4j.migrations.examples.sb;

import org.springframework.stereotype.Component;

import ac.simons.neo4j.migrations.core.JavaBasedMigration;
import ac.simons.neo4j.migrations.core.MigrationContext;

/**
* An example that migrations might also be Spring components.
* @author Michael J. Simons
*/
@Component
public class V040__AFreshSpringMigration implements JavaBasedMigration {

private final PersonRepository personRepository;

public V040__AFreshSpringMigration(PersonRepository personRepository) {
this.personRepository = personRepository;
}

@Override
public void apply(MigrationContext context) {
personRepository.save(new Person("Kasper was here"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,12 @@ void migrationsShouldHaveRun() throws Exception {

Migrations migrations = new Migrations(MigrationsConfig.defaultConfig(), driver);
MigrationChain info = migrations.info(MigrationChain.ChainBuilderMode.REMOTE);
assertThat(info.length()).isEqualTo(4);
assertThat(info.getLastAppliedVersion().map(MigrationVersion::getValue)).hasValue("030");
assertThat(info.isApplied("030")).isTrue();
assertThat(info.length()).isEqualTo(5);
assertThat(info.getLastAppliedVersion().map(MigrationVersion::getValue)).hasValue("040");
assertThat(info.isApplied("040")).isTrue();

cnt = session.executeRead(tx -> tx.run("MATCH (n:Person) RETURN count(n)").single().get(0).asLong());
assertThat(cnt).isEqualTo(1L);
}
}
}
2 changes: 1 addition & 1 deletion neo4j-migrations-examples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-examples</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion neo4j-migrations-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-maven-plugin</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion neo4j-migrations-quarkus-parent/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-quarkus-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-quarkus-deployment</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion neo4j-migrations-quarkus-parent/integration-tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-quarkus-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-quarkus-integration-tests</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion neo4j-migrations-quarkus-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-quarkus-parent</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion neo4j-migrations-quarkus-parent/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-quarkus-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-quarkus</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>eu.michael-simons.neo4j</groupId>
<artifactId>neo4j-migrations-spring-boot-starter-parent</artifactId>
<version>2.10.5-SNAPSHOT</version>
<version>2.11.0-SNAPSHOT</version>
</parent>

<artifactId>neo4j-migrations-spring-boot-autoconfigure</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2020-2024 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 ac.simons.neo4j.migrations.springframework.boot.autoconfigure;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.ObjectProvider;

import ac.simons.neo4j.migrations.core.Discoverer;
import ac.simons.neo4j.migrations.core.JavaBasedMigration;
import ac.simons.neo4j.migrations.core.MigrationContext;
import ac.simons.neo4j.migrations.core.MigrationsException;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ScanResult;

/**
* A discoverer for {@link JavaBasedMigration Java based migrations} using the Spring context, thus enable components
* being used as migrations.
*
* @author Michael J. Simons
* @since 2.11.0
*/
final class ApplicationContextAwareDiscoverer implements Discoverer<JavaBasedMigration> {

private final ObjectProvider<JavaBasedMigration> javaBasedMigrations;

ApplicationContextAwareDiscoverer(ObjectProvider<JavaBasedMigration> javaBasedMigrations) {
this.javaBasedMigrations = javaBasedMigrations;
}

@Override
public Collection<JavaBasedMigration> discover(MigrationContext context) {

var config = context.getConfig();
var result = new ArrayList<JavaBasedMigration>();

// First use all beans from the context
javaBasedMigrations.forEach(result::add);
// And keep a set of the already discovered types
var loadedClasses = result.stream().map(JavaBasedMigration::getClass)
.collect(Collectors.toSet());

// If configured, use the same algorithm as the default scanner
if (config.getPackagesToScan().length != 0) {
try (ScanResult scanResult = new ClassGraph()
.enableAllInfo()
.acceptPackages(config.getPackagesToScan())
.enableExternalClasses()
.scan()) {

scanResult
.getClassesImplementing(JavaBasedMigration.class.getName()).loadClasses(JavaBasedMigration.class)
.stream()
.filter(c -> !(Modifier.isAbstract(c.getModifiers()) || loadedClasses.contains(c)))
.map(c -> {
try {
return JavaBasedMigration.getDefaultConstructorFor(c).newInstance();
} catch (Exception e) {
throw new MigrationsException("Could not instantiate migration " + c.getName(), e);
}
}).forEach(result::add);

}
}
return List.copyOf(result);
}
}
Loading

0 comments on commit 4dce778

Please sign in to comment.