diff --git a/spring-boot-project/spring-boot-autoconfigure/pom.xml b/spring-boot-project/spring-boot-autoconfigure/pom.xml
index 497e4d8188..b81e317cc7 100755
--- a/spring-boot-project/spring-boot-autoconfigure/pom.xml
+++ b/spring-boot-project/spring-boot-autoconfigure/pom.xml
@@ -782,7 +782,7 @@
org.neo4j
- neo4j-ogm-http-driver
+ neo4j-ogm-bolt-native-types
test
@@ -790,6 +790,11 @@
neo4j-ogm-embedded-driver
test
+
+ org.neo4j
+ neo4j-ogm-http-driver
+ test
+
org.springframework
spring-test
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java
index 620dbfb0d3..ccf0c99b9f 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2018 the original author or authors.
+ * 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.
@@ -20,6 +20,9 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.neo4j.ogm.driver.NativeTypesException;
+import org.neo4j.ogm.driver.NativeTypesNotAvailableException;
+import org.neo4j.ogm.driver.NativeTypesNotSupportedException;
import org.neo4j.ogm.session.SessionFactory;
import org.neo4j.ogm.session.event.EventListener;
@@ -34,12 +37,14 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
import org.springframework.boot.autoconfigure.domain.EntityScanPackages;
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
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.lang.Nullable;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
@@ -53,6 +58,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
* @author Vince Bickers
* @author Stephane Nicoll
* @author Kazuki Shimizu
+ * @author Michael Simons
* @since 1.4.0
*/
@Configuration
@@ -73,10 +79,44 @@ public class Neo4jDataAutoConfiguration {
public SessionFactory sessionFactory(org.neo4j.ogm.config.Configuration configuration,
ApplicationContext applicationContext,
ObjectProvider eventListeners) {
- SessionFactory sessionFactory = new SessionFactory(configuration,
- getPackagesToScan(applicationContext));
- eventListeners.stream().forEach(sessionFactory::register);
- return sessionFactory;
+ try {
+ SessionFactory sessionFactory = new SessionFactory(configuration,
+ getPackagesToScan(applicationContext));
+ eventListeners.forEach(sessionFactory::register);
+ return sessionFactory;
+ }
+ catch (NativeTypesException ex) {
+ InvalidConfigurationPropertyValueException translatedMessage = translateNativeTypesException(
+ ex);
+ throw (translatedMessage != null) ? translatedMessage : ex;
+ }
+ }
+
+ @Nullable
+ private static InvalidConfigurationPropertyValueException translateNativeTypesException(
+ NativeTypesException cause) {
+
+ String propertyName = Neo4jProperties.CONFIGURATION_PREFIX + ".use-native-types";
+ boolean propertyValue = true;
+
+ if (cause instanceof NativeTypesNotAvailableException) {
+ String message = String.format(
+ "The native type module for your Neo4j-OGM driver is not available. "
+ + "Please add the following dependency to your build:%n'%s'.",
+ ((NativeTypesNotAvailableException) cause).getRequiredModule());
+ return new InvalidConfigurationPropertyValueException(propertyName,
+ propertyValue, message);
+ }
+ if (cause instanceof NativeTypesNotSupportedException) {
+ String message = String.format(
+ "The configured Neo4j-OGM driver %s does not support Neo4j native types. "
+ + "Please consider one of the drivers that support Neo4js native types like the Bolt or the embedded driver.",
+ cause.getDriverClassName());
+ return new InvalidConfigurationPropertyValueException(propertyName,
+ propertyValue, message);
+ }
+
+ return null;
}
@Bean
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jProperties.java
index d1f8f8fecd..48408be386 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jProperties.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jProperties.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2017 the original author or authors.
+ * 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.
@@ -33,11 +33,14 @@ import org.springframework.util.ClassUtils;
* @author Michael Hunger
* @author Vince Bickers
* @author Aurélien Leboulanger
+ * @author Michael Simons
* @since 1.4.0
*/
-@ConfigurationProperties(prefix = "spring.data.neo4j")
+@ConfigurationProperties(prefix = Neo4jProperties.CONFIGURATION_PREFIX)
public class Neo4jProperties implements ApplicationContextAware {
+ static final String CONFIGURATION_PREFIX = "spring.data.neo4j";
+
static final String EMBEDDED_DRIVER = "org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver";
static final String HTTP_DRIVER = "org.neo4j.ogm.drivers.http.driver.HttpDriver";
@@ -72,6 +75,12 @@ public class Neo4jProperties implements ApplicationContextAware {
*/
private Boolean openInView;
+ /**
+ * Disables the conversion of java.time.* and spatial types in Neo4j-OGM entities and
+ * uses Neo4j native types wherever possible.
+ */
+ private boolean useNativeTypes = false;
+
private final Embedded embedded = new Embedded();
private ClassLoader classLoader = Neo4jProperties.class.getClassLoader();
@@ -116,6 +125,14 @@ public class Neo4jProperties implements ApplicationContextAware {
this.openInView = openInView;
}
+ public boolean isUseNativeTypes() {
+ return this.useNativeTypes;
+ }
+
+ public void setUseNativeTypes(boolean useNativeTypes) {
+ this.useNativeTypes = useNativeTypes;
+ }
+
public Embedded getEmbedded() {
return this.embedded;
}
@@ -146,6 +163,9 @@ public class Neo4jProperties implements ApplicationContextAware {
builder.credentials(this.username, this.password);
}
builder.autoIndex(this.getAutoIndex().getName());
+ if (this.useNativeTypes) {
+ builder.useNativeTypes();
+ }
}
private void configureUriWithDefaults(Builder builder) {
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfigurationTests.java
index 44ac066639..43a67c7409 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfigurationTests.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfigurationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2018 the original author or authors.
+ * 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.
@@ -32,6 +32,7 @@ import org.springframework.boot.autoconfigure.data.neo4j.city.City;
import org.springframework.boot.autoconfigure.data.neo4j.country.Country;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
+import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
@@ -46,13 +47,14 @@ import org.springframework.data.neo4j.web.support.OpenSessionInViewInterceptor;
import org.springframework.web.context.WebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
- * Tests for {@link Neo4jDataAutoConfiguration}. Tests can't use the embedded driver as we
- * use Lucene 4 and Neo4j still requires 3.
+ * Tests for {@link Neo4jDataAutoConfiguration}. Tests should not use the embedded driver
+ * as it requires the complete Neo4j-Kernel and server to function properly.
*
* @author Stephane Nicoll
* @author Michael Hunger
@@ -116,7 +118,6 @@ public class Neo4jDataAutoConfigurationTests {
assertThat(context)
.hasSingleBean(org.neo4j.ogm.config.Configuration.class);
});
-
}
@Test
@@ -144,6 +145,50 @@ public class Neo4jDataAutoConfigurationTests {
.doesNotHaveBean(OpenSessionInViewInterceptor.class));
}
+ @Test
+ public void shouldBeAbleToUseNativeTypesWithBolt() {
+ this.contextRunner
+ .withPropertyValues("spring.data.neo4j.uri=bolt://localhost:7687",
+ "spring.data.neo4j.use-native-types:true")
+ .withConfiguration(AutoConfigurations.of(Neo4jDataAutoConfiguration.class,
+ TransactionAutoConfiguration.class))
+ .run((context) -> assertThat(context)
+ .getBean(org.neo4j.ogm.config.Configuration.class)
+ .hasFieldOrPropertyWithValue("useNativeTypes", true));
+ }
+
+ @Test
+ public void shouldDealWithNativeTypesNotAvailableException() {
+ assertThatIllegalStateException().isThrownBy(() -> {
+ this.contextRunner
+ .withClassLoader(
+ new FilteredClassLoader("org.neo4j.ogm.drivers.bolt.types"))
+ .withPropertyValues("spring.data.neo4j.uri=bolt://localhost:7687",
+ "spring.data.neo4j.use-native-types:true")
+ .withConfiguration(
+ AutoConfigurations.of(Neo4jDataAutoConfiguration.class,
+ TransactionAutoConfiguration.class))
+ .run((context) -> context.getBean(SessionFactory.class));
+ }).withRootCauseInstanceOf(InvalidConfigurationPropertyValueException.class)
+ .withStackTraceContaining(
+ "The native type module for your Neo4j-OGM driver is not available. Please add the following dependency to your build:");
+ }
+
+ @Test
+ public void shouldDealWithNativeTypesNotSupportedException() {
+ assertThatIllegalStateException().isThrownBy(() -> {
+ this.contextRunner
+ .withPropertyValues("spring.data.neo4j.uri=http://localhost:7474",
+ "spring.data.neo4j.use-native-types:true")
+ .withConfiguration(
+ AutoConfigurations.of(Neo4jDataAutoConfiguration.class,
+ TransactionAutoConfiguration.class))
+ .run((context) -> context.getBean(SessionFactory.class));
+ }).withRootCauseInstanceOf(InvalidConfigurationPropertyValueException.class)
+ .withStackTraceContaining(
+ " The configured Neo4j-OGM driver org.neo4j.ogm.drivers.http.driver.HttpDriver does not support Neo4j native types.");
+ }
+
@Test
public void eventListenersAreAutoRegistered() {
this.contextRunner.withUserConfiguration(EventListenerConfiguration.class)
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jPropertiesTests.java
index 827b574194..2fbb627739 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jPropertiesTests.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jPropertiesTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2018 the original author or authors.
+ * 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.
@@ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link Neo4jProperties}.
*
* @author Stephane Nicoll
+ * @author Michael Simons
*/
public class Neo4jPropertiesTests {
@@ -147,6 +148,21 @@ public class Neo4jPropertiesTests {
"file:relative/path/to/my.db");
}
+ @Test
+ public void nativeTypesAreSetToFalseByDefault() {
+ Neo4jProperties properties = load(true);
+ Configuration configuration = properties.createConfiguration();
+ assertThat(configuration.getUseNativeTypes()).isFalse();
+ }
+
+ @Test
+ public 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);
diff --git a/spring-boot-project/spring-boot-dependencies/pom.xml b/spring-boot-project/spring-boot-dependencies/pom.xml
index 450b917e2c..7caf4a42aa 100644
--- a/spring-boot-project/spring-boot-dependencies/pom.xml
+++ b/spring-boot-project/spring-boot-dependencies/pom.xml
@@ -2527,6 +2527,11 @@
neo4j-ogm-bolt-driver
${neo4j-ogm.version}
+
+ org.neo4j
+ neo4j-ogm-bolt-native-types
+ ${neo4j-ogm.version}
+
org.neo4j
neo4j-ogm-core
@@ -2537,6 +2542,11 @@
neo4j-ogm-embedded-driver
${neo4j-ogm.version}
+
+ org.neo4j
+ neo4j-ogm-embedded-native-types
+ ${neo4j-ogm.version}
+
org.neo4j
neo4j-ogm-http-driver
diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
index 4aaf614cd6..d36069ae00 100644
--- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
+++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
@@ -4440,6 +4440,25 @@ 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 `java.time.*` to `String` based properties or
+use one of the various native types that Neo4j provides.
+For backwards compatibility reasons the default for Neo4j-OGM is using a `String` based representation.
+To change that behaviour, please add one of `org.neo4j:neo4j-ogm-bolt-native-types` or `org.neo4j:neo4j-ogm-embedded-native-types`
+to the dependencies of your application
+and use the following property in your Spring Boot configuration:
+
+[source,properties,indent=0]
+----
+ spring.data.neo4j.use-native-types=true
+----
+
+Please refer to the Neo4j-OGM reference for more information about
+https://neo4j.com/docs/ogm-manual/current/reference/#reference:native-property-types[native property types].
+
+
+
[[boot-features-neo4j-ogm-session]]
==== Neo4jSession
By default, if you are running a web application, the session is bound to the thread for