Commit fdf93105 authored by Stephane Nicoll's avatar Stephane Nicoll

Merge branch 'gh-22647'

This upgrades to Spring Data 2020.0.0 snapshots which required some
changes in Spring Data REST and Spring Data Elasticsearch before
upgrading to Spring Data Neo4j 6.

Closes gh-22299
parents 044408e3 9bc71fe4
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -32,7 +32,6 @@ import org.springframework.boot.actuate.web.mappings.HandlerMethodDescription;
import org.springframework.boot.actuate.web.mappings.MappingDescriptionProvider;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
......@@ -51,6 +50,7 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMappi
* @author Stephane Nicoll
* @since 2.0.0
*/
@SuppressWarnings("deprecation")
public class DispatcherServletsMappingDescriptionProvider implements MappingDescriptionProvider {
private static final List<HandlerMappingDescriptionProvider<? extends HandlerMapping>> descriptionProviders;
......@@ -171,8 +171,8 @@ public class DispatcherServletsMappingDescriptionProvider implements MappingDesc
}
private static final class DelegatingHandlerMappingDescriptionProvider
implements HandlerMappingDescriptionProvider<DelegatingHandlerMapping> {
private static final class DelegatingHandlerMappingDescriptionProvider implements
HandlerMappingDescriptionProvider<org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping> {
private final List<HandlerMappingDescriptionProvider<?>> descriptionProviders;
......@@ -182,12 +182,13 @@ public class DispatcherServletsMappingDescriptionProvider implements MappingDesc
}
@Override
public Class<DelegatingHandlerMapping> getMappingClass() {
return DelegatingHandlerMapping.class;
public Class<org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping> getMappingClass() {
return org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping.class;
}
@Override
public List<DispatcherServletMappingDescription> describe(DelegatingHandlerMapping handlerMapping) {
public List<DispatcherServletMappingDescription> describe(
org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping handlerMapping) {
List<DispatcherServletMappingDescription> descriptions = new ArrayList<>();
for (HandlerMapping delegate : handlerMapping.getDelegates()) {
descriptions.addAll(
......
......@@ -171,9 +171,6 @@ dependencies {
testImplementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation("org.mockito:mockito-core")
testImplementation("org.neo4j:neo4j-ogm-bolt-native-types")
testImplementation("org.neo4j:neo4j-ogm-http-driver")
testImplementation("org.neo4j:neo4j-ogm-embedded-driver")
testImplementation("org.springframework:spring-test")
testImplementation("org.springframework.kafka:spring-kafka-test")
testImplementation("org.springframework.security:spring-security-test")
......
......@@ -16,32 +16,37 @@
package org.springframework.boot.autoconfigure.data.neo4j;
import java.util.List;
import java.util.Set;
import org.neo4j.ogm.session.SessionFactory;
import org.neo4j.ogm.session.event.EventListener;
import org.neo4j.driver.Driver;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.domain.EntityScanPackages;
import org.springframework.boot.autoconfigure.domain.EntityScanner;
import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.neo4j.transaction.Neo4jTransactionManager;
import org.springframework.data.neo4j.web.support.OpenSessionInViewInterceptor;
import org.springframework.data.neo4j.config.Neo4jDefaultCallbacksRegistrar;
import org.springframework.data.neo4j.core.DatabaseSelectionProvider;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.data.neo4j.core.Neo4jOperations;
import org.springframework.data.neo4j.core.Neo4jTemplate;
import org.springframework.data.neo4j.core.convert.Neo4jConversions;
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
import org.springframework.data.neo4j.repository.config.Neo4jRepositoryConfigurationExtension;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data Neo4j.
......@@ -51,76 +56,62 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
* @author Vince Bickers
* @author Stephane Nicoll
* @author Kazuki Shimizu
* @author Michael Simons
* @author Michael J. Simons
* @since 1.4.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ SessionFactory.class, Neo4jTransactionManager.class, PlatformTransactionManager.class })
@EnableConfigurationProperties(Neo4jProperties.class)
@Import(Neo4jBookmarkManagementConfiguration.class)
@ConditionalOnClass({ Driver.class, Neo4jTransactionManager.class, PlatformTransactionManager.class })
@EnableConfigurationProperties(Neo4jDataProperties.class)
@ConditionalOnBean(Driver.class)
@AutoConfigureBefore(TransactionAutoConfiguration.class)
@AutoConfigureAfter(Neo4jAutoConfiguration.class)
@Import(Neo4jDefaultCallbacksRegistrar.class)
public class Neo4jDataAutoConfiguration {
@Bean
@ConditionalOnMissingBean(PlatformTransactionManager.class)
public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
Neo4jTransactionManager transactionManager = new Neo4jTransactionManager(sessionFactory);
transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(transactionManager));
return transactionManager;
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(SessionFactory.class)
static class Neo4jOgmSessionFactoryConfiguration {
@Bean
@ConditionalOnMissingBean
org.neo4j.ogm.config.Configuration configuration(Neo4jProperties properties) {
return properties.createConfiguration();
public Neo4jConversions neo4jConversions() {
return new Neo4jConversions();
}
@Bean
SessionFactory sessionFactory(org.neo4j.ogm.config.Configuration configuration, BeanFactory beanFactory,
ObjectProvider<EventListener> eventListeners) {
SessionFactory sessionFactory = new SessionFactory(configuration, getPackagesToScan(beanFactory));
eventListeners.orderedStream().forEach(sessionFactory::register);
return sessionFactory;
}
private String[] getPackagesToScan(BeanFactory beanFactory) {
List<String> packages = EntityScanPackages.get(beanFactory).getPackageNames();
if (packages.isEmpty() && AutoConfigurationPackages.has(beanFactory)) {
packages = AutoConfigurationPackages.get(beanFactory);
}
return StringUtils.toStringArray(packages);
}
@ConditionalOnMissingBean
public Neo4jMappingContext neo4jMappingContext(ApplicationContext applicationContext,
Neo4jConversions neo4jConversions) throws ClassNotFoundException {
Set<Class<?>> initialEntityClasses = new EntityScanner(applicationContext).scan(Node.class);
Neo4jMappingContext context = new Neo4jMappingContext(neo4jConversions);
context.setInitialEntitySet(initialEntityClasses);
return context;
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ WebMvcConfigurer.class, OpenSessionInViewInterceptor.class })
@ConditionalOnMissingBean(OpenSessionInViewInterceptor.class)
@ConditionalOnProperty(prefix = "spring.data.neo4j", name = "open-in-view", havingValue = "true")
static class Neo4jWebConfiguration {
@Bean
OpenSessionInViewInterceptor neo4jOpenSessionInViewInterceptor() {
return new OpenSessionInViewInterceptor();
@ConditionalOnMissingBean
public DatabaseSelectionProvider databaseSelectionProvider(Neo4jDataProperties properties) {
String database = properties.getDatabase();
return (database != null) ? DatabaseSelectionProvider.createStaticDatabaseSelectionProvider(database)
: DatabaseSelectionProvider.getDefaultSelectionProvider();
}
@Bean
WebMvcConfigurer neo4jOpenSessionInViewInterceptorConfigurer(OpenSessionInViewInterceptor interceptor) {
return new WebMvcConfigurer() {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addWebRequestInterceptor(interceptor);
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_CLIENT_BEAN_NAME)
@ConditionalOnMissingBean
public Neo4jClient neo4jClient(Driver driver) {
return Neo4jClient.create(driver);
}
};
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_TEMPLATE_BEAN_NAME)
@ConditionalOnMissingBean(Neo4jOperations.class)
public Neo4jTemplate neo4jTemplate(Neo4jClient neo4jClient, Neo4jMappingContext neo4jMappingContext,
DatabaseSelectionProvider databaseNameProvider) {
return new Neo4jTemplate(neo4jClient, neo4jMappingContext, databaseNameProvider);
}
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME)
@ConditionalOnMissingBean(PlatformTransactionManager.class)
public Neo4jTransactionManager transactionManager(Driver driver, DatabaseSelectionProvider databaseNameProvider,
ObjectProvider<TransactionManagerCustomizers> optionalCustomizers) {
Neo4jTransactionManager transactionManager = new Neo4jTransactionManager(driver, databaseNameProvider);
optionalCustomizers.ifAvailable((customizer) -> customizer.customize(transactionManager));
return transactionManager;
}
}
/*
* Copyright 2012-2020 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.autoconfigure.data.neo4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Configuration properties for Spring Data Neo4j.
*
* @author Michael J. Simons
* @since 2.4.0
*/
@ConfigurationProperties(prefix = "spring.data.neo4j")
public class Neo4jDataProperties {
/**
* Database name to use. By default, the server decides the default database to use.
*/
private String database;
public String getDatabase() {
return this.database;
}
public void setDatabase(String database) {
this.database = database;
}
}
/*
* Copyright 2012-2020 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.autoconfigure.data.neo4j;
import org.neo4j.ogm.config.AutoIndexMode;
import org.neo4j.ogm.config.Configuration;
import org.neo4j.ogm.config.Configuration.Builder;
import org.springframework.beans.BeansException;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.ClassUtils;
/**
* Configuration properties for Neo4j.
*
* @author Stephane Nicoll
* @author Michael Hunger
* @author Vince Bickers
* @author Aurélien Leboulanger
* @author Michael Simons
* @since 1.4.0
*/
@ConfigurationProperties(prefix = "spring.data.neo4j")
public class Neo4jProperties implements ApplicationContextAware {
static final String EMBEDDED_DRIVER = "org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver";
static final String HTTP_DRIVER = "org.neo4j.ogm.drivers.http.driver.HttpDriver";
static final String DEFAULT_BOLT_URI = "bolt://localhost:7687";
static final String BOLT_DRIVER = "org.neo4j.ogm.drivers.bolt.driver.BoltDriver";
/**
* URI used by the driver. Auto-detected by default.
*/
private String uri;
/**
* Login user of the server.
*/
private String username;
/**
* Login password of the server.
*/
private String password;
/**
* Auto index mode.
*/
private AutoIndexMode autoIndex = AutoIndexMode.NONE;
/**
* Whether to use Neo4j native types wherever possible.
*/
private boolean useNativeTypes = false;
private final Embedded embedded = new Embedded();
private ClassLoader classLoader = Neo4jProperties.class.getClassLoader();
public String getUri() {
return this.uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public AutoIndexMode getAutoIndex() {
return this.autoIndex;
}
public void setAutoIndex(AutoIndexMode autoIndex) {
this.autoIndex = autoIndex;
}
public boolean isUseNativeTypes() {
return this.useNativeTypes;
}
public void setUseNativeTypes(boolean useNativeTypes) {
this.useNativeTypes = useNativeTypes;
}
public Embedded getEmbedded() {
return this.embedded;
}
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
this.classLoader = ctx.getClassLoader();
}
/**
* Create a {@link Configuration} based on the state of this instance.
* @return a configuration
*/
public Configuration createConfiguration() {
Builder builder = new Builder();
configure(builder);
return builder.build();
}
private void configure(Builder builder) {
if (this.uri != null) {
builder.uri(this.uri);
}
else {
configureUriWithDefaults(builder);
}
if (this.username != null && this.password != null) {
builder.credentials(this.username, this.password);
}
builder.autoIndex(getAutoIndex().getName());
if (this.useNativeTypes) {
builder.useNativeTypes();
}
}
private void configureUriWithDefaults(Builder builder) {
if (!getEmbedded().isEnabled() || !ClassUtils.isPresent(EMBEDDED_DRIVER, this.classLoader)) {
builder.uri(DEFAULT_BOLT_URI);
}
}
public static class Embedded {
/**
* Whether to enable embedded mode if the embedded driver is available.
*/
private boolean enabled = true;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
}
/*
* Copyright 2012-2020 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.autoconfigure.data.neo4j;
import org.neo4j.driver.Driver;
import reactor.core.publisher.Flux;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.neo4j.config.Neo4jDefaultReactiveCallbacksRegistrar;
import org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider;
import org.springframework.data.neo4j.core.ReactiveNeo4jClient;
import org.springframework.data.neo4j.core.ReactiveNeo4jOperations;
import org.springframework.data.neo4j.core.ReactiveNeo4jTemplate;
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;
import org.springframework.data.neo4j.repository.config.ReactiveNeo4jRepositoryConfigurationExtension;
import org.springframework.transaction.ReactiveTransactionManager;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's reactive Neo4j
* support.
*
* @author Michael J. Simons
* @author Stephane Nicoll
* @since 2.4.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Driver.class, ReactiveNeo4jTransactionManager.class, ReactiveTransactionManager.class,
Flux.class })
@ConditionalOnBean(Driver.class)
@AutoConfigureAfter(Neo4jDataAutoConfiguration.class)
@Import(Neo4jDefaultReactiveCallbacksRegistrar.class)
public class Neo4jReactiveDataAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public ReactiveDatabaseSelectionProvider reactiveDatabaseSelectionProvider(Neo4jDataProperties dataProperties) {
String database = dataProperties.getDatabase();
return (database != null) ? ReactiveDatabaseSelectionProvider.createStaticDatabaseSelectionProvider(database)
: ReactiveDatabaseSelectionProvider.getDefaultSelectionProvider();
}
@Bean(ReactiveNeo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_CLIENT_BEAN_NAME)
@ConditionalOnMissingBean
public ReactiveNeo4jClient reactiveNeo4jClient(Driver driver) {
return ReactiveNeo4jClient.create(driver);
}
@Bean(ReactiveNeo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_TEMPLATE_BEAN_NAME)
@ConditionalOnMissingBean(ReactiveNeo4jOperations.class)
public ReactiveNeo4jTemplate reactiveNeo4jTemplate(ReactiveNeo4jClient neo4jClient,
Neo4jMappingContext neo4jMappingContext, ReactiveDatabaseSelectionProvider databaseNameProvider) {
return new ReactiveNeo4jTemplate(neo4jClient, neo4jMappingContext, databaseNameProvider);
}
@Bean(ReactiveNeo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME)
@ConditionalOnMissingBean(ReactiveTransactionManager.class)
public ReactiveTransactionManager reactiveTransactionManager(Driver driver,
ReactiveDatabaseSelectionProvider databaseNameProvider) {
return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider);
}
}
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -16,50 +16,36 @@
package org.springframework.boot.autoconfigure.data.neo4j;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.neo4j.driver.Driver;
import reactor.core.publisher.Flux;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
import org.springframework.boot.autoconfigure.data.RepositoryType;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.data.neo4j.bookmark.BeanFactoryBookmarkOperationAdvisor;
import org.springframework.data.neo4j.bookmark.BookmarkInterceptor;
import org.springframework.data.neo4j.bookmark.BookmarkManager;
import org.springframework.data.neo4j.bookmark.CaffeineBookmarkManager;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;
import org.springframework.data.neo4j.repository.config.ReactiveNeo4jRepositoryConfigurationExtension;
import org.springframework.data.neo4j.repository.support.ReactiveNeo4jRepositoryFactoryBean;
/**
* Provides a {@link BookmarkManager} for Neo4j's bookmark support based on Caffeine if
* available. Depending on the application's type (web or not) the bookmark manager will
* be bound to the application or the request, as recommend by Spring Data Neo4j.
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Neo4j Reactive
* Repositories.
*
* @author Michael Simons
* @author Michael J. Simons
* @author Stephane Nicoll
* @since 2.4.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Caffeine.class, CaffeineCacheManager.class })
@ConditionalOnMissingBean(BookmarkManager.class)
@ConditionalOnBean({ BeanFactoryBookmarkOperationAdvisor.class, BookmarkInterceptor.class })
class Neo4jBookmarkManagementConfiguration {
private static final String BOOKMARK_MANAGER_BEAN_NAME = "bookmarkManager";
@Bean(BOOKMARK_MANAGER_BEAN_NAME)
@ConditionalOnWebApplication
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.INTERFACES)
BookmarkManager requestScopedBookmarkManager() {
return new CaffeineBookmarkManager();
}
@Bean(BOOKMARK_MANAGER_BEAN_NAME)
@ConditionalOnNotWebApplication
BookmarkManager singletonScopedBookmarkManager() {
return new CaffeineBookmarkManager();
}
@ConditionalOnClass({ Driver.class, ReactiveNeo4jRepository.class, Flux.class })
@ConditionalOnMissingBean({ ReactiveNeo4jRepositoryFactoryBean.class,
ReactiveNeo4jRepositoryConfigurationExtension.class })
@ConditionalOnRepositoryType(store = "neo4j", type = RepositoryType.REACTIVE)
@Import(Neo4jReactiveRepositoriesRegistrar.class)
@AutoConfigureAfter(Neo4jReactiveDataAutoConfiguration.class)
public class Neo4jReactiveRepositoriesAutoConfiguration {
}
/*
* Copyright 2012-2020 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.autoconfigure.data.neo4j;
import java.lang.annotation.Annotation;
import org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.data.neo4j.repository.config.EnableReactiveNeo4jRepositories;
import org.springframework.data.neo4j.repository.config.ReactiveNeo4jRepositoryConfigurationExtension;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
/**
* {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Neo4j reactive
* Repositories.
*
* @author Michael J. Simons
*/
class Neo4jReactiveRepositoriesRegistrar extends AbstractRepositoryConfigurationSourceSupport {
@Override
protected Class<? extends Annotation> getAnnotation() {
return EnableReactiveNeo4jRepositories.class;
}
@Override
protected Class<?> getConfiguration() {
return EnableReactiveNeo4jRepositoriesConfiguration.class;
}
@Override
protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() {
return new ReactiveNeo4jRepositoryConfigurationExtension();
}
@EnableReactiveNeo4jRepositories
private static class EnableReactiveNeo4jRepositoriesConfiguration {
}
}
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -16,13 +16,14 @@
package org.springframework.boot.autoconfigure.data.neo4j;
import org.neo4j.ogm.session.Neo4jSession;
import org.neo4j.driver.Driver;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
import org.springframework.boot.autoconfigure.data.RepositoryType;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.neo4j.repository.Neo4jRepository;
......@@ -34,10 +35,10 @@ import org.springframework.data.neo4j.repository.support.Neo4jRepositoryFactoryB
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Neo4j
* Repositories.
* <p>
* Activates when there is no bean of type {@link Neo4jRepositoryFactoryBean} configured
* in the context, the Spring Data Neo4j {@link Neo4jRepository} type is on the classpath,
* the Neo4j client driver API is on the classpath, and there is no other configured
* {@link Neo4jRepository}.
* Activates when there is no bean of type {@link Neo4jRepositoryFactoryBean} or
* {@link Neo4jRepositoryConfigurationExtension} configured in the context, the Spring
* Data Neo4j {@link Neo4jRepository} type is on the classpath, the Neo4j client driver
* API is on the classpath, and there is no other configured {@link Neo4jRepository}.
* <p>
* Once in effect, the auto-configuration is the equivalent of enabling Neo4j repositories
* using the {@link EnableNeo4jRepositories @EnableNeo4jRepositories} annotation.
......@@ -45,14 +46,14 @@ import org.springframework.data.neo4j.repository.support.Neo4jRepositoryFactoryB
* @author Dave Syer
* @author Oliver Gierke
* @author Josh Long
* @author Michael J. Simons
* @since 1.4.0
* @see EnableNeo4jRepositories
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Neo4jSession.class, Neo4jRepository.class })
@ConditionalOnClass({ Driver.class, Neo4jRepository.class })
@ConditionalOnMissingBean({ Neo4jRepositoryFactoryBean.class, Neo4jRepositoryConfigurationExtension.class })
@ConditionalOnProperty(prefix = "spring.data.neo4j.repositories", name = "enabled", havingValue = "true",
matchIfMissing = true)
@ConditionalOnRepositoryType(store = "neo4j", type = RepositoryType.IMPERATIVE)
@Import(Neo4jRepositoriesRegistrar.class)
@AutoConfigureAfter(Neo4jDataAutoConfiguration.class)
public class Neo4jRepositoriesAutoConfiguration {
......
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -23,6 +23,7 @@ import org.springframework.core.annotation.Order;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
/**
* A {@code RepositoryRestConfigurer} that applies configuration items from the
......@@ -43,7 +44,13 @@ class SpringBootRepositoryRestConfigurer implements RepositoryRestConfigurer {
private RepositoryRestProperties properties;
@Override
@SuppressWarnings("deprecation")
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
configureRepositoryRestConfiguration(config, null);
}
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) {
this.properties.applyTo(config);
}
......
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -34,12 +34,11 @@ import org.springframework.core.annotation.AliasFor;
* <li>Set the
* {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean#setPackagesToScan(String...)
* packages scanned} for JPA entities.</li>
* <li>Set the packages used with Neo4J's {@link org.neo4j.ogm.session.SessionFactory
* SessionFactory}.</li>
* <li>Set the
* {@link org.springframework.data.mapping.context.AbstractMappingContext#setInitialEntitySet(java.util.Set)
* initial entity set} used with Spring Data
* {@link org.springframework.data.mongodb.core.mapping.MongoMappingContext MongoDB},
* {@link org.springframework.data.neo4j.core.mapping.Neo4jMappingContext Neo4j},
* {@link org.springframework.data.cassandra.core.mapping.CassandraMappingContext
* Cassandra} and
* {@link org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext
......
......@@ -651,19 +651,81 @@
},
{
"name": "spring.data.neo4j.auto-index",
"defaultValue": "none"
"description": "Auto index mode.",
"defaultValue": "none",
"deprecation": {
"reason": "Automatic index creation is no longer supported.",
"level": "error"
}
},
{
"name": "spring.data.neo4j.embedded.enabled",
"type": "java.lang.Boolean",
"description": "Whether to enable embedded mode if the embedded driver is available.",
"deprecation": {
"reason": "Embedded mode is no longer supported, please use Testcontainers instead.",
"level": "error"
}
},
{
"name": "spring.data.neo4j.open-in-view",
"type": "java.lang.Boolean",
"description": "Register OpenSessionInViewInterceptor that binds a Neo4j Session to the thread for the entire processing of the request.",
"defaultValue": false
"deprecation": {
"level": "error"
}
},
{
"name": "spring.data.neo4j.password",
"type": "java.lang.String",
"description": "Login password of the server.",
"deprecation": {
"replacement": "spring.neo4j.authentication.password",
"level": "error"
}
},
{
"name": "spring.data.neo4j.repositories.enabled",
"type": "java.lang.Boolean",
"description": "Whether to enable Neo4j repositories.",
"defaultValue": true
"defaultValue": true,
"deprecation": {
"replacement": "spring.data.neo4j.repositories.type",
"level": "error"
}
},
{
"name": "spring.data.neo4j.repositories.type",
"type": "org.springframework.boot.autoconfigure.data.RepositoryType",
"description": "Type of Neo4j repositories to enable.",
"defaultValue": "auto"
},
{
"name": "spring.data.neo4j.uri",
"type": "java.lang.String",
"description": "URI used by the driver. Auto-detected by default.",
"deprecation": {
"replacement": "spring.neo4j.uri",
"level": "error"
}
},
{
"name": "spring.data.neo4j.use-native-types",
"type": "java.lang.Boolean",
"description": "Whether to use Neo4j native types wherever possible.",
"deprecation": {
"reason": "Native type support is now built-in.",
"level": "error"
}
},
{
"name": "spring.data.neo4j.username",
"type": "java.lang.String",
"description": "Login user of the server.",
"deprecation": {
"replacement": "spring.neo4j.authentication.password",
"level": "error"
}
},
{
"name": "spring.data.r2dbc.repositories.enabled",
......
......@@ -51,6 +51,8 @@ org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfigura
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
......
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -19,7 +19,10 @@ package org.springframework.boot.autoconfigure.data.neo4j;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver;
import org.neo4j.driver.Config;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.internal.logging.Slf4jLogging;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
......@@ -31,11 +34,12 @@ import org.springframework.boot.autoconfigure.data.neo4j.empty.EmptyMarker;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.neo4j.config.AbstractNeo4jConfig;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import static org.assertj.core.api.Assertions.assertThat;
......@@ -48,6 +52,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Michael Hunger
* @author Vince Bickers
* @author Stephane Nicoll
* @author Michael J. Simons
*/
class MixedNeo4jRepositoriesAutoConfigurationTests {
......@@ -94,12 +99,12 @@ class MixedNeo4jRepositoriesAutoConfigurationTests {
private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.setClassLoader(new FilteredClassLoader(EmbeddedDriver.class));
TestPropertyValues.of(environment).and("spring.datasource.initialization-mode=never").applyTo(context);
context.register(config);
context.register(DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class, Neo4jDataAutoConfiguration.class,
Neo4jRepositoriesAutoConfiguration.class);
Neo4jReactiveDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class,
Neo4jReactiveRepositoriesAutoConfiguration.class);
context.refresh();
this.context = context;
}
......@@ -108,7 +113,14 @@ class MixedNeo4jRepositoriesAutoConfigurationTests {
@TestAutoConfigurationPackage(EmptyMarker.class)
// Not this package or its parent
@EnableNeo4jRepositories(basePackageClasses = Country.class)
static class TestConfiguration {
static class TestConfiguration extends AbstractNeo4jConfig {
@Override
@Bean
public Driver driver() {
return GraphDatabase.driver("bolt://neo4j.test:7687",
Config.builder().withLogging(new Slf4jLogging()).build());
}
}
......@@ -117,7 +129,14 @@ class MixedNeo4jRepositoriesAutoConfigurationTests {
@EnableNeo4jRepositories(basePackageClasses = Country.class)
@EntityScan(basePackageClasses = City.class)
@EnableJpaRepositories(basePackageClasses = CityRepository.class)
static class MixedConfiguration {
static class MixedConfiguration extends AbstractNeo4jConfig {
@Override
@Bean
public Driver driver() {
return GraphDatabase.driver("bolt://neo4j.test:7687",
Config.builder().withLogging(new Slf4jLogging()).build());
}
}
......
/*
* Copyright 2012-2020 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.autoconfigure.data.neo4j;
import org.mockito.Mockito;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Session;
import org.neo4j.driver.SessionConfig;
import org.neo4j.driver.types.TypeSystem;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Driver configuration mocked to avoid instantiation of a real driver with connection
* creation.
*
* @author Michael J. Simons
*/
@Configuration(proxyBeanMethods = false)
class MockedDriverConfiguration {
@Bean
Driver driver() {
Driver driver = mock(Driver.class);
TypeSystem typeSystem = mock(TypeSystem.class);
Session session = mock(Session.class);
given(driver.defaultTypeSystem()).willReturn(typeSystem);
given(driver.session(Mockito.any(SessionConfig.class))).willReturn(session);
return driver;
}
}
/*
* Copyright 2012-2019 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.autoconfigure.data.neo4j;
import java.util.Base64;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.neo4j.ogm.config.AutoIndexMode;
import org.neo4j.ogm.config.Configuration;
import org.neo4j.ogm.config.Credentials;
import org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link Neo4jProperties}.
*
* @author Stephane Nicoll
* @author Michael Simons
*/
class Neo4jPropertiesTests {
private AnnotationConfigApplicationContext context;
@AfterEach
void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
void defaultUseEmbeddedInMemoryIfAvailable() {
Neo4jProperties properties = load(true);
Configuration configuration = properties.createConfiguration();
assertDriver(configuration, Neo4jProperties.EMBEDDED_DRIVER, null);
}
@Test
void defaultUseBoltDriverIfEmbeddedDriverIsNotAvailable() {
Neo4jProperties properties = load(false);
Configuration configuration = properties.createConfiguration();
assertDriver(configuration, Neo4jProperties.BOLT_DRIVER, Neo4jProperties.DEFAULT_BOLT_URI);
}
@Test
void httpUriUseHttpDriver() {
Neo4jProperties properties = load(true, "spring.data.neo4j.uri=http://localhost:7474");
Configuration configuration = properties.createConfiguration();
assertDriver(configuration, Neo4jProperties.HTTP_DRIVER, "http://localhost:7474");
}
@Test
void httpsUriUseHttpDriver() {
Neo4jProperties properties = load(true, "spring.data.neo4j.uri=https://localhost:7474");
Configuration configuration = properties.createConfiguration();
assertDriver(configuration, Neo4jProperties.HTTP_DRIVER, "https://localhost:7474");
}
@Test
void boltUriUseBoltDriver() {
Neo4jProperties properties = load(true, "spring.data.neo4j.uri=bolt://localhost:7687");
Configuration configuration = properties.createConfiguration();
assertDriver(configuration, Neo4jProperties.BOLT_DRIVER, "bolt://localhost:7687");
}
@Test
void fileUriUseEmbeddedServer() {
Neo4jProperties properties = load(true, "spring.data.neo4j.uri=file://var/tmp/graph.db");
Configuration configuration = properties.createConfiguration();
assertDriver(configuration, Neo4jProperties.EMBEDDED_DRIVER, "file://var/tmp/graph.db");
}
@Test
void credentialsAreSet() {
Neo4jProperties properties = load(true, "spring.data.neo4j.uri=http://localhost:7474",
"spring.data.neo4j.username=user", "spring.data.neo4j.password=secret");
Configuration configuration = properties.createConfiguration();
assertDriver(configuration, Neo4jProperties.HTTP_DRIVER, "http://localhost:7474");
assertCredentials(configuration, "user", "secret");
}
@Test
void credentialsAreSetFromUri() {
Neo4jProperties properties = load(true, "spring.data.neo4j.uri=https://user:secret@my-server:7474");
Configuration configuration = properties.createConfiguration();
assertDriver(configuration, Neo4jProperties.HTTP_DRIVER, "https://my-server:7474");
assertCredentials(configuration, "user", "secret");
}
@Test
void autoIndexNoneByDefault() {
Neo4jProperties properties = load(true);
Configuration configuration = properties.createConfiguration();
assertThat(configuration.getAutoIndex()).isEqualTo(AutoIndexMode.NONE);
}
@Test
void autoIndexCanBeConfigured() {
Neo4jProperties properties = load(true, "spring.data.neo4j.auto-index=validate");
Configuration configuration = properties.createConfiguration();
assertThat(configuration.getAutoIndex()).isEqualTo(AutoIndexMode.VALIDATE);
}
@Test
void embeddedModeDisabledUseBoltUri() {
Neo4jProperties properties = load(true, "spring.data.neo4j.embedded.enabled=false");
Configuration configuration = properties.createConfiguration();
assertDriver(configuration, Neo4jProperties.BOLT_DRIVER, Neo4jProperties.DEFAULT_BOLT_URI);
}
@Test
void embeddedModeWithRelativeLocation() {
Neo4jProperties properties = load(true, "spring.data.neo4j.uri=file:relative/path/to/my.db");
Configuration configuration = properties.createConfiguration();
assertDriver(configuration, Neo4jProperties.EMBEDDED_DRIVER, "file:relative/path/to/my.db");
}
@Test
void nativeTypesAreSetToFalseByDefault() {
Neo4jProperties properties = load(true);
Configuration configuration = properties.createConfiguration();
assertThat(configuration.getUseNativeTypes()).isFalse();
}
@Test
void nativeTypesCanBeConfigured() {
Neo4jProperties properties = load(true, "spring.data.neo4j.use-native-types=true");
Configuration configuration = properties.createConfiguration();
assertThat(configuration.getUseNativeTypes()).isTrue();
}
private static void assertDriver(Configuration actual, String driver, String uri) {
assertThat(actual).isNotNull();
assertThat(actual.getDriverClassName()).isEqualTo(driver);
assertThat(actual.getURI()).isEqualTo(uri);
}
private static void assertCredentials(Configuration actual, String username, String password) {
Credentials<?> credentials = actual.getCredentials();
if (username == null && password == null) {
assertThat(credentials).isNull();
}
else {
assertThat(credentials).isNotNull();
Object content = credentials.credentials();
assertThat(content).isInstanceOf(String.class);
String[] auth = new String(Base64.getDecoder().decode((String) content)).split(":");
assertThat(auth).containsExactly(username, password);
}
}
Neo4jProperties load(boolean embeddedAvailable, String... environment) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
if (!embeddedAvailable) {
ctx.setClassLoader(new FilteredClassLoader(EmbeddedDriver.class));
}
TestPropertyValues.of(environment).applyTo(ctx);
ctx.register(TestConfiguration.class);
ctx.refresh();
this.context = ctx;
return this.context.getBean(Neo4jProperties.class);
}
@org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(Neo4jProperties.class)
static class TestConfiguration {
}
}
/*
* Copyright 2012-2020 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.autoconfigure.data.neo4j;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.core.DatabaseSelection;
import org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider;
import org.springframework.data.neo4j.core.ReactiveNeo4jClient;
import org.springframework.data.neo4j.core.ReactiveNeo4jOperations;
import org.springframework.data.neo4j.core.ReactiveNeo4jTemplate;
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;
import org.springframework.transaction.ReactiveTransactionManager;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link Neo4jReactiveDataAutoConfiguration}.
*
* @author Michael J. Simons
* @author Stephane Nicoll
*/
class Neo4jReactiveDataAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(MockedDriverConfiguration.class)
.withConfiguration(AutoConfigurations.of(Neo4jAutoConfiguration.class, Neo4jDataAutoConfiguration.class,
Neo4jReactiveDataAutoConfiguration.class));
@Test
void shouldProvideDefaultDatabaseNameProvider() {
this.contextRunner.run((context) -> {
assertThat(context).hasSingleBean(ReactiveDatabaseSelectionProvider.class);
assertThat(context.getBean(ReactiveDatabaseSelectionProvider.class))
.isSameAs(ReactiveDatabaseSelectionProvider.getDefaultSelectionProvider());
});
}
@Test
void shouldUseDatabaseNameIfSet() {
this.contextRunner.withPropertyValues("spring.data.neo4j.database=test").run((context) -> {
assertThat(context).hasSingleBean(ReactiveDatabaseSelectionProvider.class);
StepVerifier.create(context.getBean(ReactiveDatabaseSelectionProvider.class).getDatabaseSelection())
.consumeNextWith((databaseSelection) -> assertThat(databaseSelection.getValue()).isEqualTo("test"))
.expectComplete();
});
}
@Test
void shouldReuseExistingDatabaseNameProvider() {
this.contextRunner.withPropertyValues("spring.data.neo4j.database=ignored")
.withUserConfiguration(CustomReactiveDatabaseSelectionProviderConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(ReactiveDatabaseSelectionProvider.class);
StepVerifier.create(context.getBean(ReactiveDatabaseSelectionProvider.class).getDatabaseSelection())
.consumeNextWith(
(databaseSelection) -> assertThat(databaseSelection.getValue()).isEqualTo("custom"))
.expectComplete();
});
}
@Test
void shouldProvideReactiveNeo4jClient() {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ReactiveNeo4jClient.class));
}
@Test
void shouldReuseExistingReactiveNeo4jClient() {
this.contextRunner
.withBean("myCustomReactiveClient", ReactiveNeo4jClient.class, () -> mock(ReactiveNeo4jClient.class))
.run((context) -> assertThat(context).hasSingleBean(ReactiveNeo4jClient.class)
.hasBean("myCustomReactiveClient"));
}
@Test
void shouldProvideReactiveNeo4jTemplate() {
this.contextRunner.withUserConfiguration(CustomReactiveDatabaseSelectionProviderConfiguration.class)
.run((context) -> {
assertThat(context).hasSingleBean(ReactiveNeo4jTemplate.class);
assertThat(context.getBean(ReactiveNeo4jTemplate.class)).extracting("databaseSelectionProvider")
.isSameAs(context.getBean(ReactiveDatabaseSelectionProvider.class));
});
}
@Test
void shouldReuseExistingReactiveNeo4jTemplate() {
this.contextRunner
.withBean("myCustomReactiveOperations", ReactiveNeo4jOperations.class,
() -> mock(ReactiveNeo4jOperations.class))
.run((context) -> assertThat(context).hasSingleBean(ReactiveNeo4jOperations.class)
.hasBean("myCustomReactiveOperations"));
}
@Test
void shouldProvideReactiveTransactionManager() {
this.contextRunner.withUserConfiguration(CustomReactiveDatabaseSelectionProviderConfiguration.class)
.run((context) -> {
assertThat(context).hasSingleBean(ReactiveNeo4jTransactionManager.class);
assertThat(context.getBean(ReactiveNeo4jTransactionManager.class))
.extracting("databaseSelectionProvider")
.isSameAs(context.getBean(ReactiveDatabaseSelectionProvider.class));
});
}
@Test
void shouldReuseExistingReactiveTransactionManager() {
this.contextRunner
.withBean("myCustomReactiveTransactionManager", ReactiveTransactionManager.class,
() -> mock(ReactiveTransactionManager.class))
.run((context) -> assertThat(context).hasSingleBean(ReactiveTransactionManager.class)
.hasBean("myCustomReactiveTransactionManager"));
}
@Configuration(proxyBeanMethods = false)
static class CustomReactiveDatabaseSelectionProviderConfiguration {
@Bean
ReactiveDatabaseSelectionProvider databaseNameProvider() {
return () -> Mono.just(DatabaseSelection.byName("custom"));
}
}
}
/*
* Copyright 2012-2020 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.autoconfigure.data.neo4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
import org.springframework.boot.autoconfigure.data.neo4j.city.City;
import org.springframework.boot.autoconfigure.data.neo4j.city.CityRepository;
import org.springframework.boot.autoconfigure.data.neo4j.city.ReactiveCityRepository;
import org.springframework.boot.autoconfigure.data.neo4j.country.CountryRepository;
import org.springframework.boot.autoconfigure.data.neo4j.country.ReactiveCountryRepository;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;
import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;
import org.springframework.data.neo4j.repository.config.EnableReactiveNeo4jRepositories;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link Neo4jReactiveRepositoriesAutoConfiguration}.
*
* @author Stephane Nicoll
* @author Michael J. Simons
*/
public class Neo4jReactiveRepositoriesAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(MockedDriverConfiguration.class)
.withConfiguration(AutoConfigurations.of(Neo4jDataAutoConfiguration.class,
Neo4jReactiveDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class,
Neo4jReactiveRepositoriesAutoConfiguration.class));
@Test
void configurationWithDefaultRepositories() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(ReactiveCityRepository.class));
}
@Test
void configurationWithNoRepositories() {
this.contextRunner.withUserConfiguration(EmptyConfiguration.class).run((context) -> assertThat(context)
.hasSingleBean(ReactiveNeo4jTransactionManager.class).doesNotHaveBean(ReactiveNeo4jRepository.class));
}
@Test
void configurationWithDisabledRepositories() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.data.neo4j.repositories.type=none")
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveNeo4jRepository.class));
}
@Test
void autoConfigurationShouldNotKickInEvenIfManualConfigDidNotCreateAnyRepositories() {
this.contextRunner.withUserConfiguration(SortOfInvalidCustomConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(ReactiveNeo4jTransactionManager.class)
.doesNotHaveBean(ReactiveNeo4jRepository.class));
}
@Test
void shouldRespectAtEnableReactiveNeo4jRepositories() {
this.contextRunner
.withUserConfiguration(SortOfInvalidCustomConfiguration.class, WithCustomReactiveRepositoryScan.class)
.withPropertyValues("spring.data.neo4j.repositories.type=reactive")
.run((context) -> assertThat(context).doesNotHaveBean(CityRepository.class)
.doesNotHaveBean(ReactiveCityRepository.class).doesNotHaveBean(CountryRepository.class)
.hasSingleBean(ReactiveCountryRepository.class));
}
@Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(City.class)
static class TestConfiguration {
}
@Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(EmptyDataPackage.class)
static class EmptyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableReactiveNeo4jRepositories("foo.bar")
@TestAutoConfigurationPackage(Neo4jReactiveRepositoriesAutoConfigurationTests.class)
static class SortOfInvalidCustomConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableReactiveNeo4jRepositories(basePackageClasses = ReactiveCountryRepository.class)
static class WithCustomReactiveRepositoryScan {
}
}
/*
* Copyright 2012-2020 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.autoconfigure.data.neo4j;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.data.neo4j.country.CountryRepository;
import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test to ensure that the properties get read and applied during the auto-configuration.
*
* @author Michael J. Simons
*/
@SpringBootTest
@Testcontainers(disabledWithoutDocker = true)
public class Neo4jRepositoriesAutoConfigurationIntegrationTests {
@Container
private static final Neo4jContainer<?> neo4jServer = new Neo4jContainer<>("neo4j:4.0");
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.neo4j.uri", neo4jServer::getBoltUrl);
registry.add("spring.neo4j.authentication.username", () -> "neo4j");
registry.add("spring.neo4j.authentication.password", neo4jServer::getAdminPassword);
}
@Autowired
private CountryRepository countryRepository;
@Test
void ensureRepositoryIsReady() {
assertThat(this.countryRepository.count()).isEqualTo(0);
}
@Configuration
@EnableNeo4jRepositories(basePackageClasses = CountryRepository.class)
@ImportAutoConfiguration({ Neo4jAutoConfiguration.class, Neo4jDataAutoConfiguration.class,
Neo4jRepositoriesAutoConfiguration.class })
static class TestConfiguration {
}
}
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -16,25 +16,26 @@
package org.springframework.boot.autoconfigure.data.neo4j;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.neo4j.ogm.session.SessionFactory;
import org.mockito.Mockito;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.data.alt.neo4j.CityNeo4jRepository;
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
import org.springframework.boot.autoconfigure.data.neo4j.city.City;
import org.springframework.boot.autoconfigure.data.neo4j.city.CityRepository;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.boot.autoconfigure.data.neo4j.city.ReactiveCityRepository;
import org.springframework.boot.autoconfigure.data.neo4j.country.CountryRepository;
import org.springframework.boot.autoconfigure.data.neo4j.country.ReactiveCountryRepository;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.repository.support.ReactiveNeo4jRepositoryFactoryBean;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Tests for {@link Neo4jRepositoriesAutoConfiguration}.
......@@ -44,73 +45,77 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
* @author Michael Hunger
* @author Vince Bickers
* @author Stephane Nicoll
* @author Michael J. Simons
*/
class Neo4jRepositoriesAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(MockedDriverConfiguration.class).withConfiguration(
AutoConfigurations.of(Neo4jDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class));
@AfterEach
void close() {
this.context.close();
@Test
void configurationWithDefaultRepositories() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(CityRepository.class));
}
@Test
void testDefaultRepositoryConfiguration() {
prepareApplicationContext(TestConfiguration.class);
assertThat(this.context.getBean(CityRepository.class)).isNotNull();
Neo4jMappingContext mappingContext = this.context.getBean(Neo4jMappingContext.class);
assertThat(mappingContext.getPersistentEntity(City.class)).isNotNull();
void configurationWithNoRepositories() {
this.contextRunner.withUserConfiguration(EmptyConfiguration.class).run((context) -> assertThat(context)
.hasSingleBean(Neo4jTransactionManager.class).doesNotHaveBean(Neo4jRepository.class));
}
@Test
void testNoRepositoryConfiguration() {
prepareApplicationContext(EmptyConfiguration.class);
assertThat(this.context.getBean(SessionFactory.class)).isNotNull();
void configurationWithDisabledRepositories() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.data.neo4j.repositories.type=none")
.run((context) -> assertThat(context).doesNotHaveBean(Neo4jRepository.class));
}
@Test
void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
prepareApplicationContext(CustomizedConfiguration.class);
assertThat(this.context.getBean(CityNeo4jRepository.class)).isNotNull();
void autoConfigurationShouldNotKickInEvenIfManualConfigDidNotCreateAnyRepositories() {
this.contextRunner.withUserConfiguration(SortOfInvalidCustomConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(Neo4jTransactionManager.class)
.doesNotHaveBean(Neo4jRepository.class));
}
@Test
void autoConfigurationShouldNotKickInEvenIfManualConfigDidNotCreateAnyRepositories() {
prepareApplicationContext(SortOfInvalidCustomConfiguration.class);
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
.isThrownBy(() -> this.context.getBean(CityRepository.class));
void shouldRespectAtEnableNeo4jRepositories() {
this.contextRunner.withUserConfiguration(SortOfInvalidCustomConfiguration.class, WithCustomRepositoryScan.class)
.run((context) -> assertThat(context).doesNotHaveBean(CityRepository.class)
.doesNotHaveBean(ReactiveCityRepository.class).hasSingleBean(CountryRepository.class)
.doesNotHaveBean(ReactiveCountryRepository.class));
}
private void prepareApplicationContext(Class<?>... configurationClasses) {
this.context = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.data.neo4j.uri=http://localhost:9797").applyTo(this.context);
this.context.register(configurationClasses);
this.context.register(Neo4jDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
@Configuration(proxyBeanMethods = false)
@EnableNeo4jRepositories(basePackageClasses = CountryRepository.class)
static class WithCustomRepositoryScan {
}
@Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(City.class)
static class TestConfiguration {
static class WithFakeEnabledReactiveNeo4jRepositories {
@Bean
ReactiveNeo4jRepositoryFactoryBean<?, ?, ?> reactiveNeo4jRepositoryFactoryBean() {
return Mockito.mock(ReactiveNeo4jRepositoryFactoryBean.class);
}
}
@Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(EmptyDataPackage.class)
static class EmptyConfiguration {
@TestAutoConfigurationPackage(City.class)
static class TestConfiguration {
}
@Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(Neo4jRepositoriesAutoConfigurationTests.class)
@EnableNeo4jRepositories(basePackageClasses = CityNeo4jRepository.class)
static class CustomizedConfiguration {
@TestAutoConfigurationPackage(EmptyDataPackage.class)
static class EmptyConfiguration {
}
@Configuration(proxyBeanMethods = false)
// To not find any repositories
@EnableNeo4jRepositories("foo.bar")
@TestAutoConfigurationPackage(Neo4jRepositoriesAutoConfigurationTests.class)
static class SortOfInvalidCustomConfiguration {
......
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -18,13 +18,12 @@ package org.springframework.boot.autoconfigure.data.neo4j.city;
import java.io.Serializable;
import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.NodeEntity;
import org.springframework.boot.autoconfigure.data.neo4j.country.Country;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
@NodeEntity
@Node
public class City implements Serializable {
private static final long serialVersionUID = 1L;
......@@ -41,9 +40,6 @@ public class City implements Serializable {
private String map;
public City() {
}
public City(String name, Country country) {
this.name = name;
this.country = country;
......
/*
* Copyright 2012-2020 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.autoconfigure.data.neo4j.city;
import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;
public interface ReactiveCityRepository extends ReactiveNeo4jRepository<City, Long> {
}
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -18,11 +18,11 @@ package org.springframework.boot.autoconfigure.data.neo4j.country;
import java.io.Serializable;
import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.NodeEntity;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
@NodeEntity
@Node
public class Country implements Serializable {
private static final long serialVersionUID = 1L;
......@@ -33,9 +33,6 @@ public class Country implements Serializable {
private String name;
public Country() {
}
public Country(String name) {
this.name = name;
}
......
/*
* Copyright 2012-2020 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.autoconfigure.data.neo4j.country;
import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;
public interface ReactiveCountryRepository extends ReactiveNeo4jRepository<Country, Long> {
}
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -42,6 +42,7 @@ import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguratio
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.assertj.core.api.Assertions.assertThat;
......@@ -76,7 +77,7 @@ class RepositoryRestMvcAutoConfigurationTests {
assertThat(this.context.getBean(RepositoryRestMvcConfiguration.class)).isNotNull();
RepositoryRestConfiguration bean = this.context.getBean(RepositoryRestConfiguration.class);
URI expectedUri = URI.create("/foo");
assertThat(bean.getBaseUri()).as("Custom basePath not set").isEqualTo(expectedUri);
assertThat(bean.getBasePath()).as("Custom basePath not set").isEqualTo(expectedUri);
BaseUri baseUri = this.context.getBean(BaseUri.class);
assertThat(expectedUri).as("Custom basePath has not been applied to BaseUri bean").isEqualTo(baseUri.getUri());
}
......@@ -119,7 +120,7 @@ class RepositoryRestMvcAutoConfigurationTests {
load(TestConfigurationWithRestMvcConfig.class, "spring.data.rest.base-path:foo");
assertThat(this.context.getBean(RepositoryRestMvcConfiguration.class)).isNotNull();
RepositoryRestConfiguration bean = this.context.getBean(RepositoryRestConfiguration.class);
assertThat(bean.getBaseUri()).isEqualTo(URI.create(""));
assertThat(bean.getBasePath()).isEqualTo(URI.create(""));
}
private void load(Class<?> config, String... environment) {
......@@ -174,7 +175,7 @@ class RepositoryRestMvcAutoConfigurationTests {
static class TestRepositoryRestConfigurer implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) {
config.setRepositoryDetectionStrategy(RepositoryDetectionStrategies.ALL);
config.setDefaultMediaType(MediaType.parseMediaType("application/my-custom-json"));
config.setMaxPageSize(78);
......
......@@ -271,7 +271,7 @@ bom {
]
}
}
library("Elasticsearch", "7.7.1") {
library("Elasticsearch", "7.8.1") {
group("org.elasticsearch") {
modules = [
"elasticsearch"
......@@ -1177,19 +1177,6 @@ bom {
]
}
}
library("Neo4j OGM", "3.2.12") {
group("org.neo4j") {
modules = [
"neo4j-ogm-api",
"neo4j-ogm-bolt-driver",
"neo4j-ogm-bolt-native-types",
"neo4j-ogm-core",
"neo4j-ogm-embedded-driver",
"neo4j-ogm-embedded-native-types",
"neo4j-ogm-http-driver"
]
}
}
library("Netty", "4.1.50.Final") {
group("io.netty") {
imports = [
......@@ -1563,7 +1550,7 @@ bom {
]
}
}
library("Spring Data Bom", "2020.0.0-M1") {
library("Spring Data Bom", "2020.0.0-SNAPSHOT") {
group("org.springframework.data") {
imports = [
"spring-data-bom"
......
......@@ -2978,7 +2978,7 @@ class ExampleIntegrationTests {
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
}
}
......
......@@ -4532,47 +4532,6 @@ Each will be called in order with the `ConfigBuilder` that is used to build the
[[boot-features-connecting-to-neo4j-embedded]]
==== Using the Embedded Mode
If you add `org.neo4j:neo4j-ogm-embedded-driver` to the dependencies of your application, Spring Boot automatically configures an in-process embedded instance of Neo4j that does not persist any data when your application shuts down.
NOTE: As the embedded Neo4j OGM driver does not provide the Neo4j kernel itself, you have to declare `org.neo4j:neo4j` as dependency yourself.
Refer to https://neo4j.com/docs/ogm-manual/current/reference/#reference:getting-started[the Neo4j OGM documentation] for a list of compatible versions.
The embedded driver takes precedence over the other drivers when there are multiple drivers on the classpath.
You can explicitly disable the embedded mode by setting `spring.data.neo4j.embedded.enabled=false`.
<<boot-features-testing-spring-boot-applications-testing-autoconfigured-neo4j-test,Data Neo4j Tests>> automatically make use of an embedded Neo4j instance if the embedded driver and Neo4j kernel are on the classpath as described above.
NOTE: You can enable persistence for the embedded mode by providing a path to a database file in your configuration, e.g. `spring.data.neo4j.uri=file://var/tmp/graph.db`.
[[boot-features-neo4j-ogm-native-types]]
==== Using Native Types
Neo4j-OGM can map some types, like those in `java.time.*`, to `String`-based properties or to one of the native types that Neo4j provides.
For backwards compatibility reasons the default for Neo4j-OGM is to use a `String`-based representation.
To use native types, add a dependency on either `org.neo4j:neo4j-ogm-bolt-native-types` or `org.neo4j:neo4j-ogm-embedded-native-types`, and configure the configprop:spring.data.neo4j.use-native-types[] property as shown in the following example:
[source,properties,indent=0,configprops]
----
spring.data.neo4j.use-native-types=true
----
[[boot-features-neo4j-ogm-session]]
==== Neo4jSession
By default, if you are running a web application, the session is bound to the thread for the entire processing of the request (that is, it uses the "Open Session in View" pattern).
If you do not want this behavior, add the following line to your `application.properties` file:
[source,properties,indent=0,configprops]
----
spring.data.neo4j.open-in-view=false
----
[[boot-features-spring-data-neo4j-repositories]]
==== Spring Data Neo4j Repositories
Spring Data includes repository support for Neo4j.
......
......@@ -42,7 +42,10 @@ org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
# AutoConfigureDataNeo4j auto-configuration imports
org.springframework.boot.test.autoconfigure.data.neo4j.AutoConfigureDataNeo4j=\
org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
......
......@@ -19,7 +19,6 @@ package org.springframework.boot.test.autoconfigure.data.neo4j;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.neo4j.ogm.session.Session;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
......@@ -27,6 +26,7 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.neo4j.core.Neo4jTemplate;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
......@@ -48,8 +48,13 @@ class DataNeo4jTestIntegrationTests {
static final Neo4jContainer<?> neo4j = new Neo4jContainer<>().withoutAuthentication()
.withStartupTimeout(Duration.ofMinutes(10));
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
}
@Autowired
private Session session;
private Neo4jTemplate neo4jTemplate;
@Autowired
private ExampleRepository exampleRepository;
......@@ -57,19 +62,13 @@ class DataNeo4jTestIntegrationTests {
@Autowired
private ApplicationContext applicationContext;
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
}
@Test
void testRepository() {
ExampleGraph exampleGraph = new ExampleGraph();
exampleGraph.setDescription("Look, new @DataNeo4jTest!");
ExampleGraph exampleGraph = new ExampleGraph("Look, new @DataNeo4jTest!");
assertThat(exampleGraph.getId()).isNull();
ExampleGraph savedGraph = this.exampleRepository.save(exampleGraph);
assertThat(savedGraph.getId()).isNotNull();
assertThat(this.session.countEntitiesOfType(ExampleGraph.class)).isEqualTo(1);
assertThat(this.neo4jTemplate.count(ExampleGraph.class)).isEqualTo(1);
}
@Test
......
......@@ -44,14 +44,14 @@ class DataNeo4jTestPropertiesIntegrationTests {
static final Neo4jContainer<?> neo4j = new Neo4jContainer<>().withoutAuthentication()
.withStartupTimeout(Duration.ofMinutes(10));
@Autowired
private Environment environment;
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
}
@Autowired
private Environment environment;
@Test
void environmentWithNewProfile() {
assertThat(this.environment.getActiveProfiles()).containsExactly("test");
......
/*
* Copyright 2012-2020 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.test.autoconfigure.data.neo4j;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.neo4j.core.ReactiveNeo4jTemplate;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Integration tests for the reactive SDN/RX Neo4j test slice.
*
* @author Michael J. Simons
* @since 2.4.0
*/
@DataNeo4jTest
@Testcontainers(disabledWithoutDocker = true)
class DataNeo4jTestReactiveIntegrationTests {
@Container
static final Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:4.0").withoutAuthentication()
.withStartupTimeout(Duration.ofMinutes(10));
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
}
@Autowired
private ReactiveNeo4jTemplate neo4jTemplate;
@Autowired
private ExampleReactiveRepository exampleRepository;
@Autowired
private ApplicationContext applicationContext;
@Test
void testRepository() {
Mono.just(new ExampleGraph("Look, new @DataNeo4jTest with reactive!")).flatMap(this.exampleRepository::save)
.as(StepVerifier::create).expectNextCount(1).verifyComplete();
StepVerifier.create(this.neo4jTemplate.count(ExampleGraph.class)).expectNext(1L).verifyComplete();
}
@Test
void didNotInjectExampleService() {
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
.isThrownBy(() -> this.applicationContext.getBean(ExampleService.class));
}
}
......@@ -45,14 +45,14 @@ class DataNeo4jTestWithIncludeFilterIntegrationTests {
static final Neo4jContainer<?> neo4j = new Neo4jContainer<>().withoutAuthentication()
.withStartupTimeout(Duration.ofMinutes(10));
@Autowired
private ExampleService service;
@DynamicPropertySource
static void neo4jProperties(DynamicPropertyRegistry registry) {
registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
}
@Autowired
private ExampleService service;
@Test
void testService() {
assertThat(this.service.hasNode(ExampleGraph.class)).isFalse();
......
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -16,17 +16,17 @@
package org.springframework.boot.test.autoconfigure.data.neo4j;
import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Property;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;
/**
* Example graph used with {@link DataNeo4jTest @DataNeo4jTest} tests.
*
* @author Eddú Meléndez
*/
@NodeEntity
@Node
public class ExampleGraph {
@Id
......@@ -36,6 +36,10 @@ public class ExampleGraph {
@Property
private String description;
public ExampleGraph(String description) {
this.description = description;
}
public Long getId() {
return this.id;
}
......
/*
* Copyright 2012-2019 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.test.autoconfigure.data.neo4j;
import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;
/**
* Example reactive repository used with {@link DataNeo4jTest @DataNeo4jTest} tests.
*
* @author Stephane Nicoll
*/
interface ExampleReactiveRepository extends ReactiveNeo4jRepository<ExampleGraph, Long> {
}
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -16,26 +16,26 @@
package org.springframework.boot.test.autoconfigure.data.neo4j;
import org.neo4j.ogm.session.Session;
import org.springframework.data.neo4j.core.Neo4jTemplate;
import org.springframework.stereotype.Service;
/**
* Example service used with {@link DataNeo4jTest @DataNeo4jTest} tests.
*
* @author Eddú Meléndez
* @author Michael J. Simons
*/
@Service
public class ExampleService {
private final Session session;
private final Neo4jTemplate neo4jTemplate;
public ExampleService(Session session) {
this.session = session;
public ExampleService(Neo4jTemplate neo4jTemplate) {
this.neo4jTemplate = neo4jTemplate;
}
public boolean hasNode(Class<?> clazz) {
return this.session.countEntitiesOfType(clazz) == 1;
return this.neo4jTemplate.count(clazz) == 1;
}
}
......@@ -14,7 +14,6 @@ dependencies {
compileOnly("org.junit.jupiter:junit-jupiter")
compileOnly("org.junit.platform:junit-platform-engine")
compileOnly("org.mockito:mockito-core")
compileOnly("org.neo4j:neo4j-ogm-core")
compileOnly("org.springframework:spring-context")
compileOnly("org.springframework.data:spring-data-redis")
compileOnly("org.testcontainers:testcontainers")
......
......@@ -56,7 +56,6 @@ dependencies {
optional("org.hibernate.validator:hibernate-validator")
optional("org.jboss:jboss-transaction-spi")
optional("org.liquibase:liquibase-core")
optional("org.neo4j:neo4j-ogm-core")
optional("org.slf4j:jul-to-slf4j")
optional("org.slf4j:slf4j-api")
optional("org.springframework:spring-messaging")
......
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
......@@ -16,11 +16,11 @@
package smoketest.data.neo4j;
import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.NodeEntity;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
@NodeEntity
@Node
public class Customer {
@Id
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment