Skip to content

Commit b7fa3d1

Browse files
committed
Update starter for Spring Data Neo4j.
This commit will update the Spring Data Neo4j Spring Boot starter, autoconfig and actuator. It will also bring in autoconfiguration for the Neo4j Java driver to enable users to work with a managed instance of the driver without the high level abstraction of Spring Data.
1 parent 0f264b6 commit b7fa3d1

File tree

42 files changed

+1619
-855
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1619
-855
lines changed

spring-boot-project/spring-boot-autoconfigure/build.gradle

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,16 +170,14 @@ dependencies {
170170
testImplementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
171171
testImplementation("org.junit.jupiter:junit-jupiter")
172172
testImplementation("org.mockito:mockito-core")
173-
testImplementation("org.neo4j:neo4j-ogm-bolt-native-types")
174-
testImplementation("org.neo4j:neo4j-ogm-http-driver")
175-
testImplementation("org.neo4j:neo4j-ogm-embedded-driver")
176173
testImplementation("org.springframework:spring-test")
177174
testImplementation("org.springframework.kafka:spring-kafka-test")
178175
testImplementation("org.springframework.security:spring-security-test")
179176
testImplementation("org.testcontainers:cassandra")
180177
testImplementation("org.testcontainers:couchbase")
181178
testImplementation("org.testcontainers:elasticsearch")
182179
testImplementation("org.testcontainers:junit-jupiter")
180+
testImplementation("org.testcontainers:neo4j")
183181
testImplementation("org.testcontainers:testcontainers")
184182
testImplementation("org.yaml:snakeyaml")
185183

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jBookmarkManagementConfiguration.java

Lines changed: 0 additions & 65 deletions
This file was deleted.

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java

Lines changed: 29 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -16,111 +16,61 @@
1616

1717
package org.springframework.boot.autoconfigure.data.neo4j;
1818

19-
import java.util.List;
19+
import java.util.Set;
2020

21-
import org.neo4j.ogm.session.SessionFactory;
22-
import org.neo4j.ogm.session.event.EventListener;
21+
import org.neo4j.driver.Driver;
2322

24-
import org.springframework.beans.factory.BeanFactory;
25-
import org.springframework.beans.factory.ObjectProvider;
26-
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
23+
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
2724
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
28-
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2926
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
30-
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
31-
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
32-
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
33-
import org.springframework.boot.autoconfigure.domain.EntityScanPackages;
34-
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
27+
import org.springframework.boot.autoconfigure.domain.EntityScanner;
28+
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
3529
import org.springframework.boot.context.properties.EnableConfigurationProperties;
30+
import org.springframework.context.ApplicationContext;
3631
import org.springframework.context.annotation.Bean;
3732
import org.springframework.context.annotation.Configuration;
3833
import org.springframework.context.annotation.Import;
39-
import org.springframework.data.neo4j.transaction.Neo4jTransactionManager;
40-
import org.springframework.data.neo4j.web.support.OpenSessionInViewInterceptor;
41-
import org.springframework.transaction.PlatformTransactionManager;
42-
import org.springframework.util.StringUtils;
43-
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
44-
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
34+
import org.springframework.data.neo4j.core.convert.Neo4jConversions;
35+
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
36+
import org.springframework.data.neo4j.core.schema.Node;
4537

4638
/**
47-
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data Neo4j.
39+
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data Neo4j. Automatic
40+
* configuration of base infrastructure that imports configuration for both imperative and
41+
* reactive Neo4j repositories. Depends on the configured Neo4j driver.
4842
*
4943
* @author Michael Hunger
5044
* @author Josh Long
5145
* @author Vince Bickers
5246
* @author Stephane Nicoll
5347
* @author Kazuki Shimizu
54-
* @author Michael Simons
48+
* @author Michael J Simons
5549
* @since 1.4.0
5650
*/
5751
@Configuration(proxyBeanMethods = false)
58-
@ConditionalOnClass({ SessionFactory.class, Neo4jTransactionManager.class, PlatformTransactionManager.class })
59-
@EnableConfigurationProperties(Neo4jProperties.class)
60-
@Import(Neo4jBookmarkManagementConfiguration.class)
52+
@ConditionalOnBean(Driver.class)
53+
@EnableConfigurationProperties(Neo4jDataProperties.class)
54+
@AutoConfigureBefore(TransactionAutoConfiguration.class)
55+
@Import({ Neo4jImperativeDataConfiguration.class, Neo4jReactiveDataConfiguration.class })
6156
public class Neo4jDataAutoConfiguration {
6257

6358
@Bean
64-
@ConditionalOnMissingBean(PlatformTransactionManager.class)
65-
public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory,
66-
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
67-
Neo4jTransactionManager transactionManager = new Neo4jTransactionManager(sessionFactory);
68-
transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(transactionManager));
69-
return transactionManager;
59+
@ConditionalOnMissingBean
60+
public Neo4jConversions neo4jConversions() {
61+
return new Neo4jConversions();
7062
}
7163

72-
@Configuration(proxyBeanMethods = false)
73-
@ConditionalOnMissingBean(SessionFactory.class)
74-
static class Neo4jOgmSessionFactoryConfiguration {
75-
76-
@Bean
77-
@ConditionalOnMissingBean
78-
org.neo4j.ogm.config.Configuration configuration(Neo4jProperties properties) {
79-
return properties.createConfiguration();
80-
}
81-
82-
@Bean
83-
SessionFactory sessionFactory(org.neo4j.ogm.config.Configuration configuration, BeanFactory beanFactory,
84-
ObjectProvider<EventListener> eventListeners) {
85-
SessionFactory sessionFactory = new SessionFactory(configuration, getPackagesToScan(beanFactory));
86-
eventListeners.orderedStream().forEach(sessionFactory::register);
87-
return sessionFactory;
88-
}
89-
90-
private String[] getPackagesToScan(BeanFactory beanFactory) {
91-
List<String> packages = EntityScanPackages.get(beanFactory).getPackageNames();
92-
if (packages.isEmpty() && AutoConfigurationPackages.has(beanFactory)) {
93-
packages = AutoConfigurationPackages.get(beanFactory);
94-
}
95-
return StringUtils.toStringArray(packages);
96-
}
97-
98-
}
99-
100-
@Configuration(proxyBeanMethods = false)
101-
@ConditionalOnWebApplication(type = Type.SERVLET)
102-
@ConditionalOnClass({ WebMvcConfigurer.class, OpenSessionInViewInterceptor.class })
103-
@ConditionalOnMissingBean(OpenSessionInViewInterceptor.class)
104-
@ConditionalOnProperty(prefix = "spring.data.neo4j", name = "open-in-view", havingValue = "true")
105-
static class Neo4jWebConfiguration {
106-
107-
@Bean
108-
OpenSessionInViewInterceptor neo4jOpenSessionInViewInterceptor() {
109-
return new OpenSessionInViewInterceptor();
110-
}
111-
112-
@Bean
113-
WebMvcConfigurer neo4jOpenSessionInViewInterceptorConfigurer(OpenSessionInViewInterceptor interceptor) {
114-
return new WebMvcConfigurer() {
115-
116-
@Override
117-
public void addInterceptors(InterceptorRegistry registry) {
118-
registry.addWebRequestInterceptor(interceptor);
119-
}
64+
@Bean
65+
@ConditionalOnMissingBean
66+
public Neo4jMappingContext neo4jMappingContext(ApplicationContext applicationContext,
67+
Neo4jConversions neo4jConversions) throws ClassNotFoundException {
12068

121-
};
122-
}
69+
Set<Class<?>> initialEntityClasses = new EntityScanner(applicationContext).scan(Node.class);
70+
Neo4jMappingContext context = new Neo4jMappingContext(neo4jConversions);
71+
context.setInitialEntitySet(initialEntityClasses);
12372

73+
return context;
12474
}
12575

12676
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.data.neo4j;
18+
19+
import org.springframework.boot.context.properties.ConfigurationProperties;
20+
import org.springframework.data.neo4j.core.DatabaseSelectionProvider;
21+
22+
/**
23+
* Configuration properties for Spring Data Neo4j.
24+
*
25+
* @author Michael J. Simons
26+
* @since 2.4.0
27+
*/
28+
@ConfigurationProperties(prefix = "spring.data.neo4j")
29+
public class Neo4jDataProperties {
30+
31+
/**
32+
* A statically configured database name. This property is only applicable when
33+
* connecting against a 4.0 cluster or server and will lead to errors if used with a
34+
* prior version of Neo4j. Leave this null (the default) to indicate that you like the
35+
* server to decide the default database to use. The database name set here will be
36+
* statically used throughout the lifetime of the application. If you need more
37+
* flexibility you can declare a bean of type {@link DatabaseSelectionProvider} which
38+
* can for example use Spring's Security Context or similar to determine the current
39+
* principal on which you could decide which database to use.
40+
*/
41+
private String database;
42+
43+
public String getDatabase() {
44+
return this.database;
45+
}
46+
47+
public void setDatabase(String database) {
48+
this.database = database;
49+
}
50+
51+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.autoconfigure.data.neo4j;
18+
19+
import org.neo4j.driver.Driver;
20+
21+
import org.springframework.beans.factory.ObjectProvider;
22+
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
23+
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
24+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
26+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
27+
import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
28+
import org.springframework.boot.autoconfigure.data.RepositoryType;
29+
import org.springframework.boot.autoconfigure.neo4j.Neo4jDriverAutoConfiguration;
30+
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
31+
import org.springframework.context.annotation.Bean;
32+
import org.springframework.context.annotation.Configuration;
33+
import org.springframework.context.annotation.Import;
34+
import org.springframework.core.annotation.Order;
35+
import org.springframework.data.neo4j.config.Neo4jDefaultCallbacksRegistrar;
36+
import org.springframework.data.neo4j.core.DatabaseSelectionProvider;
37+
import org.springframework.data.neo4j.core.Neo4jClient;
38+
import org.springframework.data.neo4j.core.Neo4jOperations;
39+
import org.springframework.data.neo4j.core.Neo4jTemplate;
40+
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
41+
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
42+
import org.springframework.data.neo4j.repository.config.Neo4jRepositoryConfigurationExtension;
43+
import org.springframework.transaction.PlatformTransactionManager;
44+
45+
/**
46+
* Internal configuration of Neo4j client and transaction manager.
47+
*
48+
* @author Michael J. Simons
49+
*/
50+
@Configuration(proxyBeanMethods = false)
51+
@ConditionalOnClass({ Neo4jTransactionManager.class, PlatformTransactionManager.class })
52+
@ConditionalOnRepositoryType(store = "neo4j", type = RepositoryType.IMPERATIVE)
53+
@AutoConfigureAfter(Neo4jDriverAutoConfiguration.class)
54+
@AutoConfigureBefore(Neo4jImperativeRepositoriesConfiguration.class)
55+
@Import(Neo4jDefaultCallbacksRegistrar.class)
56+
final class Neo4jImperativeDataConfiguration {
57+
58+
@Bean("databaseSelectionProvider")
59+
@ConditionalOnProperty(prefix = "spring.data.neo4j", name = "database")
60+
@ConditionalOnMissingBean
61+
@Order(-30)
62+
DatabaseSelectionProvider staticDatabaseSelectionProvider(Neo4jDataProperties dataProperties) {
63+
64+
return DatabaseSelectionProvider.createStaticDatabaseSelectionProvider(dataProperties.getDatabase());
65+
}
66+
67+
@Bean("databaseSelectionProvider")
68+
@ConditionalOnMissingBean
69+
@Order(-20)
70+
DatabaseSelectionProvider defaultSelectionProvider() {
71+
72+
return DatabaseSelectionProvider.getDefaultSelectionProvider();
73+
}
74+
75+
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_CLIENT_BEAN_NAME)
76+
@ConditionalOnMissingBean
77+
Neo4jClient neo4jClient(Driver driver) {
78+
return Neo4jClient.create(driver);
79+
}
80+
81+
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_TEMPLATE_BEAN_NAME)
82+
@ConditionalOnMissingBean(Neo4jOperations.class)
83+
Neo4jTemplate neo4jTemplate(Neo4jClient neo4jClient, Neo4jMappingContext neo4jMappingContext,
84+
DatabaseSelectionProvider databaseNameProvider) {
85+
86+
return new Neo4jTemplate(neo4jClient, neo4jMappingContext, databaseNameProvider);
87+
}
88+
89+
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME)
90+
@ConditionalOnMissingBean(PlatformTransactionManager.class)
91+
Neo4jTransactionManager transactionManager(Driver driver, DatabaseSelectionProvider databaseNameProvider,
92+
ObjectProvider<TransactionManagerCustomizers> optionalCustomizers) {
93+
94+
final Neo4jTransactionManager transactionManager = new Neo4jTransactionManager(driver, databaseNameProvider);
95+
optionalCustomizers.ifAvailable((customizer) -> customizer.customize(transactionManager));
96+
97+
return transactionManager;
98+
}
99+
100+
}

0 commit comments

Comments
 (0)