Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -42,6 +42,7 @@
*
* @author Eric Spiegelberg
* @author Stephane Nicoll
* @author Michael Simons
*/
public class Neo4jHealthIndicatorTests {

Expand Down Expand Up @@ -77,9 +78,8 @@ public void neo4jUp() {

@Test
public void neo4jDown() {
CypherException cypherException = new CypherException("Error executing Cypher",
"Neo.ClientError.Statement.SyntaxError",
"Unable to execute invalid Cypher");
CypherException cypherException = new CypherException(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I welcome such polish but I'd prefer to see them in a separate commit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this resolved really? I can still see the change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split into two separate commits.
I wanted to have this in one PR, as it is a breaking api change in Neo4j 3.2. Can create two PRs from it as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are seven commits right now so it's hard for me to figure out what is supposed to be squashed and what isn't.

Generally speaking, if you have something that's good to go, I very much prefer a quick PR that I can merge right away. If you don't have time to create one, that's fine as well but please squash the current commits to make that a bit more explicit. Thanks!

"Neo.ClientError.Statement.SyntaxError", "Error executing Cypher");
given(this.session.query(Neo4jHealthIndicator.CYPHER, Collections.emptyMap()))
.willThrow(cypherException);
Health health = this.neo4jHealthIndicator.health();
Expand Down
7 changes: 6 additions & 1 deletion spring-boot-project/spring-boot-autoconfigure/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -782,14 +782,19 @@
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-http-driver</artifactId>
<artifactId>neo4j-ogm-bolt-native-types</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-embedded-driver</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-http-driver</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -20,6 +20,9 @@

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;

Expand All @@ -34,12 +37,14 @@
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;
Expand All @@ -53,6 +58,7 @@
* @author Vince Bickers
* @author Stephane Nicoll
* @author Kazuki Shimizu
* @author Michael Simons
* @since 1.4.0
*/
@Configuration
Expand All @@ -73,10 +79,44 @@ public org.neo4j.ogm.config.Configuration configuration(Neo4jProperties properti
public SessionFactory sessionFactory(org.neo4j.ogm.config.Configuration configuration,
ApplicationContext applicationContext,
ObjectProvider<EventListener> 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
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -33,11 +33,14 @@
* @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";
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -116,6 +125,14 @@ public void setOpenInView(Boolean openInView) {
this.openInView = openInView;
}

public boolean isUseNativeTypes() {
return this.useNativeTypes;
}

public void setUseNativeTypes(boolean useNativeTypes) {
this.useNativeTypes = useNativeTypes;
}

public Embedded getEmbedded() {
return this.embedded;
}
Expand Down Expand Up @@ -146,6 +163,9 @@ private void configure(Builder builder) {
builder.credentials(this.username, this.password);
}
builder.autoIndex(this.getAutoIndex().getName());
if (this.useNativeTypes) {
builder.useNativeTypes();
}
}

private void configureUriWithDefaults(Builder builder) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -32,6 +32,7 @@
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;
Expand All @@ -46,13 +47,14 @@
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
Expand Down Expand Up @@ -116,7 +118,6 @@ public void customConfiguration() {
assertThat(context)
.hasSingleBean(org.neo4j.ogm.config.Configuration.class);
});

}

@Test
Expand Down Expand Up @@ -144,6 +145,50 @@ public void openSessionInViewInterceptorCanBeDisabled() {
.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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -35,6 +35,7 @@
* Tests for {@link Neo4jProperties}.
*
* @author Stephane Nicoll
* @author Michael Simons
*/
public class Neo4jPropertiesTests {

Expand Down Expand Up @@ -147,6 +148,21 @@ public void embeddedModeWithRelativeLocation() {
"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);
Expand Down
12 changes: 11 additions & 1 deletion spring-boot-project/spring-boot-dependencies/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
<mssql-jdbc.version>6.4.0.jre8</mssql-jdbc.version>
<mysql.version>8.0.15</mysql.version>
<nekohtml.version>1.9.22</nekohtml.version>
<neo4j-ogm.version>3.1.7</neo4j-ogm.version>
<neo4j-ogm.version>3.2.0-alpha04</neo4j-ogm.version>
<netty.version>4.1.33.Final</netty.version>
<netty-tcnative.version>2.0.20.Final</netty-tcnative.version>
<nio-multipart-parser.version>1.1.0</nio-multipart-parser.version>
Expand Down Expand Up @@ -2527,6 +2527,11 @@
<artifactId>neo4j-ogm-bolt-driver</artifactId>
<version>${neo4j-ogm.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-bolt-native-types</artifactId>
<version>${neo4j-ogm.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-core</artifactId>
Expand All @@ -2537,6 +2542,11 @@
<artifactId>neo4j-ogm-embedded-driver</artifactId>
<version>${neo4j-ogm.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-embedded-native-types</artifactId>
<version>${neo4j-ogm.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-http-driver</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down