DATAGRAPH-1103 - Apply Spring Data Code Formatting Settings.

This commit applied the Spring Data Code Formatting Settings
37b34a56ce/etc/ide
through the Eclipse Code Formatter for IDEA.

# Conflicts:
#	pom.xml
#	spring-data-neo4j/pom.xml
This commit is contained in:
Michael J. Simons
2018-07-23 12:30:40 +02:00
parent f89a69c903
commit e43330e3e6
201 changed files with 3467 additions and 3702 deletions

359
pom.xml
View File

@@ -1,192 +1,193 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j-parent</artifactId>
<version>5.0.9.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j-parent</artifactId>
<version>5.0.9.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Spring Data Neo4j</name>
<description>Neo4j support for Spring Data</description>
<url>http://projects.spring.io/spring-data-neo4j</url>
<name>Spring Data Neo4j</name>
<description>Neo4j support for Spring Data</description>
<url>http://projects.spring.io/spring-data-neo4j</url>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.0.9.BUILD-SNAPSHOT</version>
</parent>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.0.9.BUILD-SNAPSHOT</version>
</parent>
<modules>
<module>spring-data-neo4j</module>
<module>spring-data-neo4j-distribution</module>
</modules>
<modules>
<module>spring-data-neo4j</module>
<module>spring-data-neo4j-distribution</module>
</modules>
<properties>
<project.type>multi</project.type>
<dist.id>spring-data-neo4j</dist.id>
<neo4j.ogm.version>3.0.4</neo4j.ogm.version>
<springdata.commons>2.0.9.BUILD-SNAPSHOT</springdata.commons>
<source.level>1.8</source.level>
</properties>
<properties>
<project.type>multi</project.type>
<dist.id>spring-data-neo4j</dist.id>
<neo4j.ogm.version>3.0.4</neo4j.ogm.version>
<springdata.commons>2.0.9.BUILD-SNAPSHOT</springdata.commons>
<source.level>1.8</source.level>
</properties>
<developers>
<developer>
<id>vbickers</id>
<name>Vince Bickers</name>
<email>vince at graphaware.com</email>
<organization>GraphAware</organization>
<organizationUrl>http://www.graphaware.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>GMT</timezone>
</developer>
<developer>
<id>atg</id>
<name>Adam George</name>
<email>adam at graphaware.com</email>
<organization>GraphAware</organization>
<organizationUrl>http://www.graphaware.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>GMT</timezone>
</developer>
<developer>
<id>bachmanm</id>
<name>Michal Bachman</name>
<email>michal at graphaware.com</email>
<organization>GraphAware</organization>
<organizationUrl>http://www.graphaware.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>GMT</timezone>
</developer>
<developer>
<id>lmisquitta</id>
<name>Luanne Misquitta</name>
<email>luanne at graphaware.com</email>
<organization>GraphAware</organization>
<organizationUrl>http://www.graphaware.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+5:30</timezone>
</developer>
<developer>
<id>mangrish</id>
<name>Mark Angrish</name>
<email>mark at graphaware.com</email>
<organization>GraphAware</organization>
<organizationUrl>http://www.graphaware.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+11</timezone>
</developer>
<developer>
<id>jasperblues</id>
<name>Jasper Blues</name>
<email>jasper at graphaware.com</email>
<organization>GraphAware</organization>
<organizationUrl>http://www.graphaware.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+8</timezone>
</developer>
<developer>
<id>mhunger</id>
<name>Michael Hunger</name>
<email>michael.hunger at neotechnology.com</email>
<organization>Neo Technology</organization>
<organizationUrl>http://www.neotechnology.com</organizationUrl>
<roles>
<role>Project Lead</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>ogierke</id>
<name>Oliver Gierke</name>
<email>ogierke at gopivotal.com</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.spring.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>trisberg</id>
<name>Thomas Risberg</name>
<email>trisberg at gopivotal.com</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.spring.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>-5</timezone>
</developer>
<developer>
<id>mpollack</id>
<name>Mark Pollack</name>
<email>mpollack at gopivotal.com</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.spring.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>-5</timezone>
</developer>
</developers>
<developers>
<developer>
<id>vbickers</id>
<name>Vince Bickers</name>
<email>vince at graphaware.com</email>
<organization>GraphAware</organization>
<organizationUrl>http://www.graphaware.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>GMT</timezone>
</developer>
<developer>
<id>atg</id>
<name>Adam George</name>
<email>adam at graphaware.com</email>
<organization>GraphAware</organization>
<organizationUrl>http://www.graphaware.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>GMT</timezone>
</developer>
<developer>
<id>bachmanm</id>
<name>Michal Bachman</name>
<email>michal at graphaware.com</email>
<organization>GraphAware</organization>
<organizationUrl>http://www.graphaware.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>GMT</timezone>
</developer>
<developer>
<id>lmisquitta</id>
<name>Luanne Misquitta</name>
<email>luanne at graphaware.com</email>
<organization>GraphAware</organization>
<organizationUrl>http://www.graphaware.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+5:30</timezone>
</developer>
<developer>
<id>mangrish</id>
<name>Mark Angrish</name>
<email>mark at graphaware.com</email>
<organization>GraphAware</organization>
<organizationUrl>http://www.graphaware.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+11</timezone>
</developer>
<developer>
<id>jasperblues</id>
<name>Jasper Blues</name>
<email>jasper at graphaware.com</email>
<organization>GraphAware</organization>
<organizationUrl>http://www.graphaware.com</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+8</timezone>
</developer>
<developer>
<id>mhunger</id>
<name>Michael Hunger</name>
<email>michael.hunger at neotechnology.com</email>
<organization>Neo Technology</organization>
<organizationUrl>http://www.neotechnology.com</organizationUrl>
<roles>
<role>Project Lead</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>ogierke</id>
<name>Oliver Gierke</name>
<email>ogierke at gopivotal.com</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.spring.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>+1</timezone>
</developer>
<developer>
<id>trisberg</id>
<name>Thomas Risberg</name>
<email>trisberg at gopivotal.com</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.spring.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>-5</timezone>
</developer>
<developer>
<id>mpollack</id>
<name>Mark Pollack</name>
<email>mpollack at gopivotal.com</email>
<organization>Pivotal</organization>
<organizationUrl>http://www.spring.io</organizationUrl>
<roles>
<role>Developer</role>
</roles>
<timezone>-5</timezone>
</developer>
</developers>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.jfrog.buildinfo</groupId>
<artifactId>artifactory-maven-plugin</artifactId>
<inherited>false</inherited>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.jfrog.buildinfo</groupId>
<artifactId>artifactory-maven-plugin</artifactId>
<inherited>false</inherited>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<repositories>
<repository>
<id>neo4j</id>
<url>http://m2.neo4j.org/content/repositories/releases</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
<repository>
<id>neo4j-snapshots</id>
<url>http://m2.neo4j.org/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
<repository>
<id>spring-libs-snapshot</id>
<url>https://repo.spring.io/libs-snapshot</url>
</repository>
</repositories>
<repositories>
<repository>
<id>neo4j</id>
<url>http://m2.neo4j.org/content/repositories/releases</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
<repository>
<id>neo4j-snapshots</id>
<url>http://m2.neo4j.org/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
<repository>
<id>spring-libs-snapshot</id>
<url>https://repo.spring.io/libs-snapshot</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-plugins-release</id>
<url>https://repo.spring.io/plugins-release</url>
</pluginRepository>
</pluginRepositories>
<pluginRepositories>
<pluginRepository>
<id>spring-plugins-release</id>
<url>https://repo.spring.io/plugins-release</url>
</pluginRepository>
</pluginRepositories>
</project>

View File

@@ -12,189 +12,190 @@
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-data-neo4j</artifactId>
<artifactId>spring-data-neo4j</artifactId>
<name>Spring Data Neo4J - Core</name>
<description>Neo4J support for Spring Data</description>
<name>Spring Data Neo4J - Core</name>
<description>Neo4J support for Spring Data</description>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j-parent</artifactId>
<version>5.0.9.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j-parent</artifactId>
<version>5.0.9.BUILD-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<ogm.properties>ogm-bolt.properties</ogm.properties>
<el-api.version>2.2</el-api.version>
<java-module-name>spring.data.neo4j</java-module-name>
<project.root>${basedir}/..</project.root>
</properties>
<properties>
<ogm.properties>ogm-bolt.properties</ogm.properties>
<el-api.version>2.2</el-api.version>
<java-module-name>spring.data.neo4j</java-module-name>
<project.root>${basedir}/..</project.root>
</properties>
<dependencies>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<!-- Spring Data -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-data-commons</artifactId>
<version>${springdata.commons}</version>
</dependency>
<!-- Spring Data -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-data-commons</artifactId>
<version>${springdata.commons}</version>
</dependency>
<!-- CDI -->
<!-- Dependency order required to build against CDI 1.0 and test with CDI 2.0 -->
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jcdi_2.0_spec</artifactId>
<version>1.0.1</version>
<scope>test</scope>
</dependency>
<!-- CDI -->
<!-- Dependency order required to build against CDI 1.0 and test with CDI 2.0 -->
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jcdi_2.0_spec</artifactId>
<version>1.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.interceptor</groupId>
<artifactId>javax.interceptor-api</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.interceptor</groupId>
<artifactId>javax.interceptor-api</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>${cdi}</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>${cdi}</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>${javax-annotation-api}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>${javax-annotation-api}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-se</artifactId>
<version>${webbeans}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-se</artifactId>
<version>${webbeans}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<!-- JSR 303 Validation -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>${validation}</version>
<optional>true</optional>
</dependency>
<!-- JSR 303 Validation -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>${validation}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.2.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.2.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<!-- Cache -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.5.2</version>
<optional>true</optional>
</dependency>
<!-- Cache -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.5.2</version>
<optional>true</optional>
</dependency>
<!-- Neo4j OGM -->
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-core</artifactId>
<version>${neo4j.ogm.version}</version>
</dependency>
<!-- Neo4j OGM -->
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-core</artifactId>
<version>${neo4j.ogm.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-bolt-driver</artifactId>
<version>${neo4j.ogm.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-bolt-driver</artifactId>
<version>${neo4j.ogm.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-test</artifactId>
<version>${neo4j.ogm.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-security-enterprise</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-test</artifactId>
<version>${neo4j.ogm.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-security-enterprise</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</dependencies>
</project>

View File

@@ -23,10 +23,11 @@ import org.springframework.data.annotation.QueryAnnotation;
/**
* Specifies the depth of the query. Used with derived finders.
*
* @author Luanne Misquitta
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@QueryAnnotation
@Documented
public @interface Depth {

View File

@@ -13,19 +13,22 @@
package org.springframework.data.neo4j.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
import org.springframework.data.neo4j.bookmark.BookmarkManagementConfiguration;
import java.lang.annotation.*;
/**
* Enables bookmark management
* <p>
* Bean implementing {@link org.springframework.data.neo4j.bookmark.BookmarkManager} interface needs to exist in the
* context. Default implementation {@link org.springframework.data.neo4j.bookmark.CaffeineBookmarkManager} exists.
* Use scope of the bean to control how bookmarks are managed.
* singleton - suitable for application wide bookmarks, e.g. fat clients
* request,session - suitable for web applications
* context. Default implementation {@link org.springframework.data.neo4j.bookmark.CaffeineBookmarkManager} exists. Use
* scope of the bean to control how bookmarks are managed. singleton - suitable for application wide bookmarks, e.g. fat
* clients request,session - suitable for web applications
* <p>
* NOTE: Only usable with OGM Bolt driver.
*

View File

@@ -13,13 +13,18 @@
package org.springframework.data.neo4j.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
import org.springframework.data.auditing.DateTimeProvider;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.neo4j.repository.config.Neo4jAuditingRegistrar;
import java.lang.annotation.*;
/**
* Annotation to enable auditing in MongoDB via annotation configuration.
*

View File

@@ -13,9 +13,13 @@
package org.springframework.data.neo4j.annotation;
import org.springframework.data.annotation.QueryAnnotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.*;
import org.springframework.data.annotation.QueryAnnotation;
/**
* Annotation to declare finder queries directly on repository methods.
@@ -29,16 +33,16 @@ import java.lang.annotation.*;
@Documented
public @interface Query {
static final String CLASS = "org.springframework.data.neo4j.annotation.Query";
static final String VALUE = "value";
static final String CLASS = "org.springframework.data.neo4j.annotation.Query";
static final String VALUE = "value";
/**
* Defines the Cypher query to be executed when the annotated method is called.
*/
String value() default "";
/**
* Defines the Cypher query to be executed when the annotated method is called.
*/
String value() default "";
/**
* @return simpler count-query to be executed for @{see Pageable}-support
*/
String countQuery() default "";
/**
* @return simpler count-query to be executed for @{see Pageable}-support
*/
String countQuery() default "";
}

View File

@@ -13,7 +13,11 @@
package org.springframework.data.neo4j.annotation;
import java.lang.annotation.*;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to be applied to interfaces and classes onto which arbitrary Cypher query results are to be mapped.
@@ -25,6 +29,6 @@ import java.lang.annotation.*;
@Documented
public @interface QueryResult {
// no annotation properties needed
// no annotation properties needed
}

View File

@@ -13,20 +13,23 @@
package org.springframework.data.neo4j.annotation;
import java.lang.annotation.*;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Indicates that a transactional operation will use bookmarks that are currently stored in BookmarkManager when
* creating Neo4j session.
* Must be used on a method with @Transactional annotation.
* May be used on class - applies to all methods or on specific methods.
* creating Neo4j session. Must be used on a method with @Transactional annotation. May be used on class - applies to
* all methods or on specific methods.
* <p>
*
* @author Frantisek Hartman
* @see EnableBookmarkManagement
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
public @interface UseBookmark {

View File

@@ -26,8 +26,7 @@ public class BookmarkInfo implements Serializable {
private boolean useBookmark;
private Collection<String> bookmarks;
public BookmarkInfo() {
}
public BookmarkInfo() {}
public BookmarkInfo(boolean useBookmark) {
this.useBookmark = true;

View File

@@ -21,16 +21,14 @@ import org.springframework.context.annotation.Role;
/**
* Configuration used by @{@link org.springframework.data.neo4j.annotation.EnableBookmarkManagement}
* <p>
* Note on bookmark management implementation:
* The implementation closely follows implementation of @EnableTransactionManagement or @EnableCaching, with simplified
* pointcut.
* Note on bookmark management implementation: The implementation closely follows implementation
* of @EnableTransactionManagement or @EnableCaching, with simplified pointcut.
* <p>
* The bookmark interceptor will set BookmarkInfo thread local when a methods is annotated with @UseBookmark.
* It is executed before transactional advice (see setOrder(0) ).
* Neo4j transaction manager then uses {@link BookmarkManager} bean to retrieve currently stored bookmarks and begins
* new transaction using these bookmarks.
* After commit new bookmark is stored in the BookmarkManager, replacing the bookmarks used to begin the transaction.
* The user needs to provide the BookmarkManager bean.
* The bookmark interceptor will set BookmarkInfo thread local when a methods is annotated with @UseBookmark. It is
* executed before transactional advice (see setOrder(0) ). Neo4j transaction manager then uses {@link BookmarkManager}
* bean to retrieve currently stored bookmarks and begins new transaction using these bookmarks. After commit new
* bookmark is stored in the BookmarkManager, replacing the bookmarks used to begin the transaction. The user needs to
* provide the BookmarkManager bean.
*
* @author Frantisek Hartman
*/
@@ -46,7 +44,6 @@ public class BookmarkManagementConfiguration {
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BookmarkInterceptor bookmarkInterceptor() {

View File

@@ -13,11 +13,11 @@
package org.springframework.data.neo4j.bookmark;
import java.lang.reflect.Method;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.data.neo4j.annotation.UseBookmark;
import java.lang.reflect.Method;
/**
* Pointcut for methods marked with @{@link UseBookmark}
*
@@ -33,7 +33,7 @@ public class BookmarkOperationPointcut extends StaticMethodMatcherPointcut {
// method matches if @UseBookmark is on class, is true and not on method or
// @UseBookmark is on method and is true
// it is needed to cover @UseBookmark on class and @UseBookmark(false) on method
return ((classAnnotation != null) && classAnnotation.value() && methodAnnotation == null) ||
((methodAnnotation != null) && methodAnnotation.value());
return ((classAnnotation != null) && classAnnotation.value() && methodAnnotation == null)
|| ((methodAnnotation != null) && methodAnnotation.value());
}
}

View File

@@ -13,13 +13,13 @@
package org.springframework.data.neo4j.bookmark;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.Collection;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
/**
* Implementation of the bookmark manager using Caffeine cache
* <p>
@@ -32,10 +32,7 @@ public class CaffeineBookmarkManager implements BookmarkManager {
private final Cache<String, String> cache;
public CaffeineBookmarkManager() {
cache = Caffeine.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(1, TimeUnit.MINUTES)
.build();
cache = Caffeine.newBuilder().maximumSize(10_000).expireAfterWrite(1, TimeUnit.MINUTES).build();
}
/**

View File

@@ -13,23 +13,22 @@
package org.springframework.data.neo4j.conversion;
import java.lang.reflect.ParameterizedType;
import org.neo4j.ogm.metadata.ClassInfo;
import org.neo4j.ogm.metadata.FieldInfo;
import org.neo4j.ogm.metadata.MetaData;
import org.neo4j.ogm.metadata.MethodInfo;
import org.neo4j.ogm.typeconversion.AttributeConverter;
import org.neo4j.ogm.typeconversion.ConversionCallback;
import org.neo4j.ogm.typeconversion.ProxyAttributeConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.core.convert.converter.Converter;
import java.lang.reflect.ParameterizedType;
import org.springframework.core.convert.support.GenericConversionService;
/**
* Specialisation of {@link GenericConversionService} that creates Spring-compatible converters from those known by the mapping
* {@link MetaData}, allowing the OGM type converters to be reused throughout a Spring application.
* Specialisation of {@link GenericConversionService} that creates Spring-compatible converters from those known by the
* mapping {@link MetaData}, allowing the OGM type converters to be reused throughout a Spring application.
*
* @author Adam George
* @author Luanne Misquitta
@@ -37,80 +36,77 @@ import java.lang.reflect.ParameterizedType;
*/
public class MetaDataDrivenConversionService extends GenericConversionService implements ConversionCallback {
private static final Logger logger = LoggerFactory.getLogger(MetaDataDrivenConversionService.class);
private static final Logger logger = LoggerFactory.getLogger(MetaDataDrivenConversionService.class);
/**
* Constructs a new {@link MetaDataDrivenConversionService} based on the given {@link MetaData}.
*
* @param metaData The OGM {@link MetaData} from which to elicit type converters configured in the underlying object-graph
* mapping layer
*/
public MetaDataDrivenConversionService(MetaData metaData) {
metaData.registerConversionCallback(this);
/**
* Constructs a new {@link MetaDataDrivenConversionService} based on the given {@link MetaData}.
*
* @param metaData The OGM {@link MetaData} from which to elicit type converters configured in the underlying
* object-graph mapping layer
*/
public MetaDataDrivenConversionService(MetaData metaData) {
metaData.registerConversionCallback(this);
for (ClassInfo classInfo : metaData.persistentEntities()) {
for (FieldInfo fieldInfo : classInfo.propertyFields()) {
if (fieldInfo.hasPropertyConverter()) {
addWrappedConverter(fieldInfo.getPropertyConverter());
}
}
}
}
for (ClassInfo classInfo : metaData.persistentEntities()) {
for (FieldInfo fieldInfo : classInfo.propertyFields()) {
if (fieldInfo.hasPropertyConverter()) {
addWrappedConverter(fieldInfo.getPropertyConverter());
}
}
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void addWrappedConverter(final AttributeConverter attributeConverter) {
if (attributeConverter instanceof ProxyAttributeConverter) {
return;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void addWrappedConverter(final AttributeConverter attributeConverter) {
if (attributeConverter instanceof ProxyAttributeConverter) {
return;
}
Converter toGraphConverter = new Converter() {
@Override
public Object convert(Object source) {
return attributeConverter.toGraphProperty(source);
}
};
Converter toEntityConverter = new Converter() {
@Override
public Object convert(Object source) {
return attributeConverter.toEntityAttribute(source);
}
};
Converter toGraphConverter = new Converter() {
@Override
public Object convert(Object source) {
return attributeConverter.toGraphProperty(source);
}
};
Converter toEntityConverter = new Converter() {
@Override
public Object convert(Object source) {
return attributeConverter.toEntityAttribute(source);
}
};
ParameterizedType pt = (ParameterizedType) attributeConverter.getClass().getGenericInterfaces()[0];
Class<?> sourceType, targetType;
if (pt.getActualTypeArguments()[0] instanceof Class) {
sourceType = (Class<?>) pt.getActualTypeArguments()[0];
} else { // the argument may be a Collection for example
sourceType = (Class<?>) ((ParameterizedType) pt.getActualTypeArguments()[0]).getActualTypeArguments()[0];
}
ParameterizedType pt = (ParameterizedType) attributeConverter.getClass().getGenericInterfaces()[0];
Class<?> sourceType, targetType;
if (pt.getActualTypeArguments()[0] instanceof Class) {
sourceType = (Class<?>) pt.getActualTypeArguments()[0];
}
else { //the argument may be a Collection for example
sourceType = (Class<?>)((ParameterizedType) pt.getActualTypeArguments()[0]).getActualTypeArguments()[0];
}
if (pt.getActualTypeArguments()[1] instanceof Class) {
targetType = (Class<?>) pt.getActualTypeArguments()[1];
} else {
targetType = (Class<?>) ((ParameterizedType) pt.getActualTypeArguments()[1]).getActualTypeArguments()[1];
if (pt.getActualTypeArguments()[1] instanceof Class) {
targetType = (Class<?>) pt.getActualTypeArguments()[1];
}
else {
targetType = (Class<?>)((ParameterizedType) pt.getActualTypeArguments()[1]).getActualTypeArguments()[1];
}
}
if (canConvert(sourceType, targetType) && canConvert(targetType, sourceType)) {
logger.info("Not adding Spring-compatible converter for " + attributeConverter.getClass()
+ " because one that does the same job has already been registered with the ConversionService.");
} else {
// It could be argued that this is wrong as it potentially overrides a registered converted that doesn't handle
// both directions, but I've decided that it's better to ensure the same converter is used for load and save.
addConverter(sourceType, targetType, toGraphConverter);
addConverter(targetType, sourceType, toEntityConverter);
}
}
if (canConvert(sourceType, targetType) && canConvert(targetType, sourceType)) {
logger.info("Not adding Spring-compatible converter for " + attributeConverter.getClass()
+ " because one that does the same job has already been registered with the ConversionService.");
} else {
// It could be argued that this is wrong as it potentially overrides a registered converted that doesn't handle
// both directions, but I've decided that it's better to ensure the same converter is used for load and save.
addConverter(sourceType, targetType, toGraphConverter);
addConverter(targetType, sourceType, toEntityConverter);
}
}
@Override
public <T> T convert(Class<T> targetType, Object value) {
if (value == null) {
return null;
}
return convert(value, targetType);
}
@Override
public <T> T convert(Class<T> targetType, Object value) {
if (value == null) {
return null;
}
return convert(value, targetType);
}
}

View File

@@ -11,15 +11,14 @@
*
*/
package org.springframework.data.neo4j.conversion;
import org.neo4j.ogm.typeconversion.CompositeAttributeConverter;
import org.springframework.data.geo.Point;
import java.util.HashMap;
import java.util.Map;
import org.neo4j.ogm.typeconversion.CompositeAttributeConverter;
import org.springframework.data.geo.Point;
/**
* Converts latitude and longitude properties on a node entity to an instance of Point and vice-versa.
*
@@ -28,24 +27,24 @@ import java.util.Map;
*/
public class PointConverter implements CompositeAttributeConverter<Point> {
@Override
public Map<String, ?> toGraphProperties(Point point) {
Map<String, Double> properties = new HashMap<>();
if (point != null) {
properties.put("latitude", point.getX());
properties.put("longitude", point.getY());
}
return properties;
}
@Override
public Map<String, ?> toGraphProperties(Point point) {
Map<String, Double> properties = new HashMap<>();
if (point != null) {
properties.put("latitude", point.getX());
properties.put("longitude", point.getY());
}
return properties;
}
@Override
public Point toEntityAttribute(Map<String, ?> map) {
Double latitude = (Double) map.get("latitude");
Double longitude = (Double) map.get("longitude");
if (latitude != null && longitude != null) {
return new Point(latitude, longitude);
}
return null;
}
@Override
public Point toEntityAttribute(Map<String, ?> map) {
Double latitude = (Double) map.get("latitude");
Double longitude = (Double) map.get("longitude");
if (latitude != null && longitude != null) {
return new Point(latitude, longitude);
}
return null;
}
}
}

View File

@@ -60,14 +60,18 @@ public class Neo4jErrorStatusCodes {
errors.put("Neo.ClientError.Statement.SemanticError", NonTransientDataAccessException.class);
errors.put("Neo.ClientError.Statement.SyntaxError", InvalidDataAccessResourceUsageException.class);
errors.put("Neo.ClientError.Statement.TypeError", InvalidDataAccessResourceUsageException.class);
errors.put("Neo.ClientError.Transaction.ForbiddenDueToTransactionType", InvalidDataAccessResourceUsageException.class);
errors.put("Neo.ClientError.Transaction.TransactionAccessedConcurrently", InvalidDataAccessResourceUsageException.class);
errors.put("Neo.ClientError.Transaction.TransactionEventHandlerFailed", InvalidDataAccessResourceUsageException.class);
errors.put("Neo.ClientError.Transaction.ForbiddenDueToTransactionType",
InvalidDataAccessResourceUsageException.class);
errors.put("Neo.ClientError.Transaction.TransactionAccessedConcurrently",
InvalidDataAccessResourceUsageException.class);
errors.put("Neo.ClientError.Transaction.TransactionEventHandlerFailed",
InvalidDataAccessResourceUsageException.class);
errors.put("Neo.ClientError.Transaction.TransactionHookFailed", InvalidDataAccessResourceUsageException.class);
errors.put("Neo.ClientError.Transaction.TransactionMarkedAsFailed", ConcurrencyFailureException.class);
errors.put("Neo.ClientError.Transaction.TransactionNotFound", InvalidDataAccessResourceUsageException.class);
errors.put("Neo.ClientError.Transaction.TransactionTerminated", InvalidDataAccessResourceUsageException.class);
errors.put("Neo.ClientError.Transaction.TransactionValidationFailed", InvalidDataAccessResourceUsageException.class);
errors.put("Neo.ClientError.Transaction.TransactionValidationFailed",
InvalidDataAccessResourceUsageException.class);
errors.put("Neo.DatabaseError.General.IndexCorruptionDetected", DataAccessResourceFailureException.class);
errors.put("Neo.DatabaseError.General.SchemaCorruptionDetected", DataAccessResourceFailureException.class);
errors.put("Neo.DatabaseError.General.UnknownError", UncategorizedDataAccessException.class);

View File

@@ -12,10 +12,14 @@
*/
package org.springframework.data.neo4j.mapping;
import static java.util.Collections.*;
import java.lang.reflect.Field;
import org.neo4j.ogm.annotation.typeconversion.Convert;
import org.neo4j.ogm.metadata.MetaData;
import org.neo4j.ogm.metadata.ClassInfo;
import org.neo4j.ogm.metadata.FieldInfo;
import org.neo4j.ogm.metadata.MetaData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mapping.context.AbstractMappingContext;
@@ -23,18 +27,10 @@ import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.TypeInformation;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.Objects;
import static java.util.Collections.singleton;
/**
* This class implements Spring Data's MappingContext interface, scavenging the required data from the OGM's metadata in order
* to for SDN to play nicely with Spring Data REST.
*
* The main thing to note is that this class is effectively a container shim for {@code ClassInfo} objects. We don't reload all
* the mapping information again.
* This class implements Spring Data's MappingContext interface, scavenging the required data from the OGM's metadata in
* order to for SDN to play nicely with Spring Data REST. The main thing to note is that this class is effectively a
* container shim for {@code ClassInfo} objects. We don't reload all the mapping information again.
*
* @author Vince Bickers
* @author Adam George
@@ -43,80 +39,84 @@ import static java.util.Collections.singleton;
*/
public class Neo4jMappingContext extends AbstractMappingContext<Neo4jPersistentEntity<?>, Neo4jPersistentProperty> {
private static final Logger logger = LoggerFactory.getLogger(Neo4jMappingContext.class);
private static final Logger logger = LoggerFactory.getLogger(Neo4jMappingContext.class);
private final MetaData metaData;
private final MetaData metaData;
/**
* Constructs a new {@link Neo4jMappingContext} based on the persistent entities in the given {@link MetaData}.
*
* @param metaData The OGM {@link MetaData} from which to extract the persistent entities
*/
public Neo4jMappingContext(MetaData metaData) {
this.metaData = metaData;
metaData.persistentEntities().stream().filter(k -> k.getUnderlyingClass() != null).forEach(k -> addPersistentEntity(k.getUnderlyingClass()));
logger.info("Neo4jMappingContext initialisation completed");
}
/**
* Constructs a new {@link Neo4jMappingContext} based on the persistent entities in the given {@link MetaData}.
*
* @param metaData The OGM {@link MetaData} from which to extract the persistent entities
*/
public Neo4jMappingContext(MetaData metaData) {
this.metaData = metaData;
metaData.persistentEntities().stream().filter(k -> k.getUnderlyingClass() != null)
.forEach(k -> addPersistentEntity(k.getUnderlyingClass()));
logger.info("Neo4jMappingContext initialisation completed");
}
@Override
protected <T> Neo4jPersistentEntity<?> createPersistentEntity(TypeInformation<T> typeInformation) {
logger.debug("Creating Neo4jPersistentEntity from type information: {}", typeInformation);
return new Neo4jPersistentEntity<>(typeInformation);
}
@Override
protected <T> Neo4jPersistentEntity<?> createPersistentEntity(TypeInformation<T> typeInformation) {
logger.debug("Creating Neo4jPersistentEntity from type information: {}", typeInformation);
return new Neo4jPersistentEntity<>(typeInformation);
}
@Override
protected Neo4jPersistentProperty createPersistentProperty(Property property, Neo4jPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
@Override
protected Neo4jPersistentProperty createPersistentProperty(Property property, Neo4jPersistentEntity<?> owner,
SimpleTypeHolder simpleTypeHolder) {
ClassInfo owningClassInfo = this.metaData.classInfo(owner.getType().getName());
ClassInfo owningClassInfo = this.metaData.classInfo(owner.getType().getName());
Field propertyField = property.getField().orElse(null);
Field propertyField = property.getField().orElse(null);
if (!property.isFieldBacked() && owningClassInfo != null) {
FieldInfo fieldInfo = owningClassInfo.propertyFieldByName(property.getName());
if (fieldInfo == null) {
fieldInfo = owningClassInfo.relationshipFieldByName(property.getName());
}
if (fieldInfo != null) {
propertyField = owningClassInfo.getField(fieldInfo);
} else {
// there is no field, probably because descriptor gave us a field name derived from a getter
logger.debug("Couldn't resolve a concrete field corresponding to property {} on {} ",
property.getName(), owningClassInfo.name());
}
}
if (!property.isFieldBacked() && owningClassInfo != null) {
FieldInfo fieldInfo = owningClassInfo.propertyFieldByName(property.getName());
if (fieldInfo == null) {
fieldInfo = owningClassInfo.relationshipFieldByName(property.getName());
}
if (fieldInfo != null) {
propertyField = owningClassInfo.getField(fieldInfo);
} else {
// there is no field, probably because descriptor gave us a field name derived from a getter
logger.debug("Couldn't resolve a concrete field corresponding to property {} on {} ", property.getName(),
owningClassInfo.name());
}
}
return new Neo4jPersistentProperty(owningClassInfo, property, owner,
updateSimpleTypeHolder(simpleTypeHolder, propertyField));
}
return new Neo4jPersistentProperty(owningClassInfo, property, owner,
updateSimpleTypeHolder(simpleTypeHolder, propertyField));
}
private SimpleTypeHolder updateSimpleTypeHolder(SimpleTypeHolder currentSimpleTypeHolder, Field field) {
if (field == null) {
return currentSimpleTypeHolder;
}
private SimpleTypeHolder updateSimpleTypeHolder(SimpleTypeHolder currentSimpleTypeHolder, Field field) {
if (field == null) {
return currentSimpleTypeHolder;
}
final Class<?> fieldType = field.getType().isArray() ? field.getType().getComponentType() : field.getType();
final Class<?> fieldType = field.getType().isArray() ? field.getType().getComponentType() : field.getType();
if (shouldUpdateSimpleTypes(currentSimpleTypeHolder, field, fieldType)) {
SimpleTypeHolder updatedSimpleTypeHolder = new SimpleTypeHolder(singleton(fieldType), currentSimpleTypeHolder);
setSimpleTypeHolder(updatedSimpleTypeHolder);
return updatedSimpleTypeHolder;
}
return currentSimpleTypeHolder;
}
if (shouldUpdateSimpleTypes(currentSimpleTypeHolder, field, fieldType)) {
SimpleTypeHolder updatedSimpleTypeHolder = new SimpleTypeHolder(singleton(fieldType), currentSimpleTypeHolder);
setSimpleTypeHolder(updatedSimpleTypeHolder);
return updatedSimpleTypeHolder;
}
return currentSimpleTypeHolder;
}
private boolean shouldUpdateSimpleTypes(SimpleTypeHolder currentSimpleTypeHolder, Field field, Class<?> rawFieldType) {
if (field.isAnnotationPresent(Convert.class)) {
return true;
}
private boolean shouldUpdateSimpleTypes(SimpleTypeHolder currentSimpleTypeHolder, Field field,
Class<?> rawFieldType) {
if (field.isAnnotationPresent(Convert.class)) {
return true;
}
if (currentSimpleTypeHolder.isSimpleType(rawFieldType) || rawFieldType.isInterface()) {
return false;
}
if (this.metaData.classInfo(rawFieldType.getName()) == null) {
logger.info("No class information found in OGM meta-data for {} so treating as simple type for SD Commons", rawFieldType);
return true;
}
return false;
}
if (currentSimpleTypeHolder.isSimpleType(rawFieldType) || rawFieldType.isInterface()) {
return false;
}
if (this.metaData.classInfo(rawFieldType.getName()) == null) {
logger.info("No class information found in OGM meta-data for {} so treating as simple type for SD Commons",
rawFieldType);
return true;
}
return false;
}
}

View File

@@ -12,8 +12,6 @@
*/
package org.springframework.data.neo4j.mapping;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mapping.PersistentProperty;
@@ -21,22 +19,20 @@ import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.util.TypeInformation;
/**
* This class implements Spring Data's PersistentEntity interface, scavenging the required data from the OGM's mapping classes
* in order to for SDN to play nicely with Spring Data REST.
*
* The main thing to note is that this class is effectively a shim for ClassInfo. We don't reload all the mapping information
* again.
* This class implements Spring Data's PersistentEntity interface, scavenging the required data from the OGM's mapping
* classes in order to for SDN to play nicely with Spring Data REST. The main thing to note is that this class is
* effectively a shim for ClassInfo. We don't reload all the mapping information again.
* <p>
* These attributes do not appear to be used/needed for SDN 4 to inter-operate correctly with SD-REST:
* </p>
* <ul>
* <li>typeAlias</li>
* <li>typeInformation</li>
* <li>preferredConstructor (we always use the default constructor)</li>
* <li>versionProperty</li>
* <li>typeAlias</li>
* <li>typeInformation</li>
* <li>preferredConstructor (we always use the default constructor)</li>
* <li>versionProperty</li>
* </ul>
* Consequently their associated getter methods always return default values of null or [true|false] However, because these
* method calls are not expected, we also log a warning message if they get invoked
* Consequently their associated getter methods always return default values of null or [true|false] However, because
* these method calls are not expected, we also log a warning message if they get invoked
*
* @author Vince Bickers
* @author Adam George
@@ -45,33 +41,33 @@ import org.springframework.data.util.TypeInformation;
*/
public class Neo4jPersistentEntity<T> extends BasicPersistentEntity<T, Neo4jPersistentProperty> {
private static final Logger logger = LoggerFactory.getLogger(Neo4jPersistentEntity.class);
private static final Logger logger = LoggerFactory.getLogger(Neo4jPersistentEntity.class);
/**
* Constructs a new {@link Neo4jPersistentEntity} based on the given type information.
*
* @param information The {@link TypeInformation} upon which to base this persistent entity.
*/
public Neo4jPersistentEntity(TypeInformation<T> information) {
super(information);
}
/**
* Constructs a new {@link Neo4jPersistentEntity} based on the given type information.
*
* @param information The {@link TypeInformation} upon which to base this persistent entity.
*/
public Neo4jPersistentEntity(TypeInformation<T> information) {
super(information);
}
@Override
public boolean hasVersionProperty() {
logger.debug("[entity].hasVersionProperty() returns false"); // by design
return false;
}
@Override
public boolean hasVersionProperty() {
logger.debug("[entity].hasVersionProperty() returns false"); // by design
return false;
}
@Override
public Neo4jPersistentProperty getVersionProperty() {
logger.debug("[entity].getVersionProperty() returns null"); // by design
return null;
}
@Override
public Neo4jPersistentProperty getVersionProperty() {
logger.debug("[entity].getVersionProperty() returns null"); // by design
return null;
}
@Override
public boolean isVersionProperty(PersistentProperty<?> property) {
logger.debug("[entity].isIdProperty({}) returns false", property); // again, by design
return false;
}
@Override
public boolean isVersionProperty(PersistentProperty<?> property) {
logger.debug("[entity].isIdProperty({}) returns false", property); // again, by design
return false;
}
}

View File

@@ -27,11 +27,10 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.neo4j.annotation.QueryResult;
/**
* This class implements Spring Data's PersistentProperty interface, scavenging the required data from the
* OGM's mapping classes in order to for SDN to play nicely with Spring Data REST.
* The main thing to note is that this class is effectively a shim for FieldInfo. We don't reload
* all the mapping information again.
* We do not yet support getter/setter access to entity properties.
* This class implements Spring Data's PersistentProperty interface, scavenging the required data from the OGM's mapping
* classes in order to for SDN to play nicely with Spring Data REST. The main thing to note is that this class is
* effectively a shim for FieldInfo. We don't reload all the mapping information again. We do not yet support
* getter/setter access to entity properties.
* <p>
* These attributes do not appear to be used/needed for SDN 4 to inter-operate correctly with SD-REST:
* </p>
@@ -42,8 +41,8 @@ import org.springframework.data.neo4j.annotation.QueryResult;
* <li>isTransient (we never supply transient classes to the Spring mapping context)</li>
* <li>isWritable (we don't currently support read-only fields)</li>
* </ul>
* Consequently their associated getter methods always return default values of null or [true|false]
* However, because these method calls are not expected, we also log a warning message if they get invoked
* Consequently their associated getter methods always return default values of null or [true|false] However, because
* these method calls are not expected, we also log a warning message if they get invoked
*
* @author Vince Bickers
* @author Adam George
@@ -58,46 +57,51 @@ public class Neo4jPersistentProperty extends AnnotationBasedPersistentProperty<N
private final boolean isIdProperty;
/**
* Constructs a new {@link Neo4jPersistentProperty} based on the given arguments.
*
* @param owningClassInfo The {@link ClassInfo} of the object of which the property field is a member
* @param property The property
* @param owner The owning {@link PersistentEntity} that corresponds to the given {@code ClassInfo}
* @param simpleTypeHolder The {@link SimpleTypeHolder} that dictates whether the type of this property is considered simple
* or not
*/
public Neo4jPersistentProperty(ClassInfo owningClassInfo, Property property,
PersistentEntity<?, Neo4jPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
super(property, owner, simpleTypeHolder);
if (owningClassInfo == null) {
logger.warn("Owning ClassInfo is null for property: {}", property);
}
if ((owningClassInfo !=null && owningClassInfo.getUnderlyingClass()!=null && simpleTypeHolder.isSimpleType(owningClassInfo.getUnderlyingClass()))
|| owner.getType().isEnum()) { //TODO refactor all these null checks
this.isIdProperty = false;
}
else {
this.isIdProperty = resolveWhetherIdProperty(owningClassInfo, property);
}
}
/**
* Constructs a new {@link Neo4jPersistentProperty} based on the given arguments.
*
* @param owningClassInfo The {@link ClassInfo} of the object of which the property field is a member
* @param property The property
* @param owner The owning {@link PersistentEntity} that corresponds to the given {@code ClassInfo}
* @param simpleTypeHolder The {@link SimpleTypeHolder} that dictates whether the type of this property is considered
* simple or not
*/
public Neo4jPersistentProperty(ClassInfo owningClassInfo, Property property,
PersistentEntity<?, Neo4jPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
super(property, owner, simpleTypeHolder);
if (owningClassInfo == null) {
logger.warn("Owning ClassInfo is null for property: {}", property);
}
if ((owningClassInfo != null && owningClassInfo.getUnderlyingClass() != null
&& simpleTypeHolder.isSimpleType(owningClassInfo.getUnderlyingClass())) || owner.getType().isEnum()) { // TODO
// refactor
// all
// these
// null
// checks
this.isIdProperty = false;
} else {
this.isIdProperty = resolveWhetherIdProperty(owningClassInfo, property);
}
}
private static boolean resolveWhetherIdProperty(ClassInfo owningClassInfo, Property property) {
if (owningClassInfo == null || owningClassInfo.isInterface() || owningClassInfo.annotationsInfo().get(QueryResult.class.getName()) != null || owningClassInfo.isEnum()) {
// no ID properties on @QueryResult or non-concrete objects
return false;
} else {
try {
return property.getField() //
.filter(field ->owningClassInfo.getField(owningClassInfo.identityField()).equals(field)) //
.isPresent();}
catch (MetadataException noIdentityField) {
logger.warn("No identity field found for class of type: {} when creating persistent property for : {}",
owningClassInfo.name(), property);
return false;
}
}
}
private static boolean resolveWhetherIdProperty(ClassInfo owningClassInfo, Property property) {
if (owningClassInfo == null || owningClassInfo.isInterface()
|| owningClassInfo.annotationsInfo().get(QueryResult.class.getName()) != null || owningClassInfo.isEnum()) {
// no ID properties on @QueryResult or non-concrete objects
return false;
} else {
try {
return property.getField() //
.filter(field -> owningClassInfo.getField(owningClassInfo.identityField()).equals(field)) //
.isPresent();
} catch (MetadataException noIdentityField) {
logger.warn("No identity field found for class of type: {} when creating persistent property for : {}",
owningClassInfo.name(), property);
return false;
}
}
}
@Override
public boolean isIdProperty() {
@@ -123,8 +127,8 @@ public class Neo4jPersistentProperty extends AnnotationBasedPersistentProperty<N
}
/**
* Determines whether or not this property should be considered an association to another entity or whether it's
* just a simple property that should be shown as a value.
* Determines whether or not this property should be considered an association to another entity or whether it's just
* a simple property that should be shown as a value.
* <p>
* This implementation works by looking for non-transient members annotated with <code>@Relationship</code>.
* </p>
@@ -133,10 +137,8 @@ public class Neo4jPersistentProperty extends AnnotationBasedPersistentProperty<N
*/
@Override
public boolean isAssociation() {
return !isTransient() &&
(isAnnotationPresent(Relationship.class)
|| isAnnotationPresent(StartNode.class)
|| isAnnotationPresent(EndNode.class));
return !isTransient() && (isAnnotationPresent(Relationship.class) || isAnnotationPresent(StartNode.class)
|| isAnnotationPresent(EndNode.class));
}
@Override

View File

@@ -57,7 +57,8 @@ public interface Neo4jRepository<T, ID extends Serializable> extends PagingAndSo
/**
* Returns a {@link Page} of entities meeting the paging restriction provided in the {@code Pageable} object.
* {@link Page#getTotalPages()} returns an estimation of the total number of pages and should not be relied upon for accuracy.
* {@link Page#getTotalPages()} returns an estimation of the total number of pages and should not be relied upon for
* accuracy.
*
* @param pageable
* @return a page of entities
@@ -66,7 +67,8 @@ public interface Neo4jRepository<T, ID extends Serializable> extends PagingAndSo
/**
* Returns a {@link Page} of entities meeting the paging restriction provided in the {@code Pageable} object.
* {@link Page#getTotalPages()} returns an estimation of the total number of pages and should not be relied upon for accuracy.
* {@link Page#getTotalPages()} returns an estimation of the total number of pages and should not be relied upon for
* accuracy.
*
* @param pageable
* @param depth

View File

@@ -16,17 +16,18 @@
package org.springframework.data.neo4j.repository.cdi;
import org.neo4j.ogm.session.Session;
import org.springframework.data.neo4j.repository.support.Neo4jRepositoryFactory;
import org.springframework.data.repository.cdi.CdiRepositoryBean;
import org.springframework.data.repository.config.CustomRepositoryImplementationDetector;
import java.lang.annotation.Annotation;
import java.util.Optional;
import java.util.Set;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import java.lang.annotation.Annotation;
import java.util.Optional;
import java.util.Set;
import org.neo4j.ogm.session.Session;
import org.springframework.data.neo4j.repository.support.Neo4jRepositoryFactory;
import org.springframework.data.repository.cdi.CdiRepositoryBean;
import org.springframework.data.repository.config.CustomRepositoryImplementationDetector;
/**
* {@link org.springframework.data.repository.cdi.CdiRepositoryBean} to create Neo4j repository instances via CDI.
@@ -35,33 +36,34 @@ import java.util.Set;
* @since 4.2
*/
public class Neo4jCdiRepositoryBean<T> extends CdiRepositoryBean<T> {
private final Bean<Session> sessionBean;
private final Bean<Session> sessionBean;
/**
* Creates a new {@link Neo4jCdiRepositoryBean}.
*
* @param sessionBean must not be {@literal null}.
* @param qualifiers must not be {@literal null}.
* @param repositoryType must not be {@literal null}.
* @param beanManager must not be {@literal null}.
* @param detector detector for the custom {@link org.springframework.data.repository.Repository} implementations
* {@link CustomRepositoryImplementationDetector}, can be {@literal null}.
*/
public Neo4jCdiRepositoryBean(Bean<Session> sessionBean, Set<Annotation> qualifiers, Class<T> repositoryType,
BeanManager beanManager, Optional<CustomRepositoryImplementationDetector> detector) {
super(qualifiers, repositoryType, beanManager, detector);
this.sessionBean = sessionBean;
}
/**
* Creates a new {@link Neo4jCdiRepositoryBean}.
*
* @param sessionBean must not be {@literal null}.
* @param qualifiers must not be {@literal null}.
* @param repositoryType must not be {@literal null}.
* @param beanManager must not be {@literal null}.
* @param detector detector for the custom {@link org.springframework.data.repository.Repository} implementations
* {@link CustomRepositoryImplementationDetector}, can be {@literal null}.
*/
public Neo4jCdiRepositoryBean(Bean<Session> sessionBean, Set<Annotation> qualifiers, Class<T> repositoryType,
BeanManager beanManager, Optional<CustomRepositoryImplementationDetector> detector) {
super(qualifiers, repositoryType, beanManager, detector);
this.sessionBean = sessionBean;
}
@Override
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType, Optional<Object> customImplementation) {
@Override
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType,
Optional<Object> customImplementation) {
Session session = getDependencyInstance(sessionBean, Session.class);
Session session = getDependencyInstance(sessionBean, Session.class);
Neo4jRepositoryFactory factory = new Neo4jRepositoryFactory(session);
Neo4jRepositoryFactory factory = new Neo4jRepositoryFactory(session);
return customImplementation //
.map(impl -> factory.getRepository(repositoryType, impl)) //
.orElseGet(() -> factory.getRepository(repositoryType));
}
return customImplementation //
.map(impl -> factory.getRepository(repositoryType, impl)) //
.orElseGet(() -> factory.getRepository(repositoryType));
}
}

View File

@@ -16,18 +16,6 @@
package org.springframework.data.neo4j.repository.cdi;
import org.neo4j.ogm.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.repository.cdi.CdiRepositoryBean;
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.UnsatisfiedResolutionException;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.ProcessBean;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.HashMap;
@@ -37,6 +25,19 @@ import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.UnsatisfiedResolutionException;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.ProcessBean;
import org.neo4j.ogm.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.repository.cdi.CdiRepositoryBean;
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
/**
* CDI extension to export Neo4j repositories.
*
@@ -45,68 +46,66 @@ import java.util.Set;
*/
public class Neo4jCdiRepositoryExtension extends CdiRepositoryExtensionSupport {
private static final Logger LOG = LoggerFactory.getLogger(Neo4jCdiRepositoryExtension.class);
private final Map<Set<Annotation>, Bean<Session>> sessions = new HashMap<Set<Annotation>, Bean<Session>>();
private static final Logger LOG = LoggerFactory.getLogger(Neo4jCdiRepositoryExtension.class);
private final Map<Set<Annotation>, Bean<Session>> sessions = new HashMap<Set<Annotation>, Bean<Session>>();
public Neo4jCdiRepositoryExtension() {
LOG.info("Activating CDI extension for Spring Data Neo4j repositories.");
}
public Neo4jCdiRepositoryExtension() {
LOG.info("Activating CDI extension for Spring Data Neo4j repositories.");
}
@SuppressWarnings("unchecked")
<X> void processBean(@Observes ProcessBean<X> processBean) {
Bean<X> bean = processBean.getBean();
@SuppressWarnings("unchecked")
<X> void processBean(@Observes ProcessBean<X> processBean) {
Bean<X> bean = processBean.getBean();
for (Type type : bean.getTypes()) {
if (type instanceof Class<?> && Session.class.isAssignableFrom((Class<?>) type)) {
for (Type type : bean.getTypes()) {
if (type instanceof Class<?> && Session.class.isAssignableFrom((Class<?>) type)) {
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Discovered %s with qualifiers %s.", Session.class.getName(),
bean.getQualifiers()));
}
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Discovered %s with qualifiers %s.", Session.class.getName(), bean.getQualifiers()));
}
sessions.put(new HashSet<Annotation>(bean.getQualifiers()), (Bean<Session>) bean);
}
}
}
sessions.put(new HashSet<Annotation>(bean.getQualifiers()), (Bean<Session>) bean);
}
}
}
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
for (Entry<Class<?>, Set<Annotation>> entry : getRepositoryTypes()) {
for (Entry<Class<?>, Set<Annotation>> entry : getRepositoryTypes()) {
Class<?> repositoryType = entry.getKey();
Set<Annotation> qualifiers = entry.getValue();
Class<?> repositoryType = entry.getKey();
Set<Annotation> qualifiers = entry.getValue();
// Create the bean representing the repository.
CdiRepositoryBean<?> repositoryBean = createRepositoryBean(repositoryType, qualifiers, beanManager);
if (LOG.isInfoEnabled()) {
LOG.info(String.format("Registering bean for %s with qualifiers %s.", repositoryType.getName(),
qualifiers));
}
// Create the bean representing the repository.
CdiRepositoryBean<?> repositoryBean = createRepositoryBean(repositoryType, qualifiers, beanManager);
if (LOG.isInfoEnabled()) {
LOG.info(String.format("Registering bean for %s with qualifiers %s.", repositoryType.getName(), qualifiers));
}
// Register the bean to the container.
registerBean(repositoryBean);
afterBeanDiscovery.addBean(repositoryBean);
}
}
// Register the bean to the container.
registerBean(repositoryBean);
afterBeanDiscovery.addBean(repositoryBean);
}
}
/**
* Creates a {@link Bean}.
*
* @param <T> The type of the repository.
* @param repositoryType The class representing the repository.
* @param beanManager The BeanManager instance.
* @return The bean.
*/
private <T> CdiRepositoryBean<T> createRepositoryBean(Class<T> repositoryType, Set<Annotation> qualifiers,
BeanManager beanManager) {
Bean<Session> sessionBean = this.sessions.get(qualifiers);
/**
* Creates a {@link Bean}.
*
* @param <T> The type of the repository.
* @param repositoryType The class representing the repository.
* @param beanManager The BeanManager instance.
* @return The bean.
*/
private <T> CdiRepositoryBean<T> createRepositoryBean(Class<T> repositoryType, Set<Annotation> qualifiers,
BeanManager beanManager) {
Bean<Session> sessionBean = this.sessions.get(qualifiers);
if (sessionBean == null) {
throw new UnsatisfiedResolutionException(String.format(
"Unable to resolve a bean for '%s' with qualifiers %s.", Session.class.getName(), qualifiers));
}
if (sessionBean == null) {
throw new UnsatisfiedResolutionException(
String.format("Unable to resolve a bean for '%s' with qualifiers %s.", Session.class.getName(), qualifiers));
}
return new Neo4jCdiRepositoryBean<T>(sessionBean, qualifiers, repositoryType, beanManager,
Optional.of(getCustomImplementationDetector()));
}
return new Neo4jCdiRepositoryBean<T>(sessionBean, qualifiers, repositoryType, beanManager,
Optional.of(getCustomImplementationDetector()));
}
}

View File

@@ -13,7 +13,12 @@
package org.springframework.data.neo4j.repository.config;
import java.lang.annotation.*;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.context.annotation.ComponentScan;
@@ -37,93 +42,93 @@ import org.springframework.transaction.PlatformTransactionManager;
@Import(Neo4jRepositoriesRegistrar.class)
public @interface EnableNeo4jRepositories {
/**
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.:
* {@code @EnableExperimentalNeo4jRepositories("org.my.pkg")} instead of
* {@code @EnableExperimentalNeo4jRepositories(basePackages="org.my.pkg")}.
*/
String[] value() default {};
/**
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.:
* {@code @EnableExperimentalNeo4jRepositories("org.my.pkg")} instead of
* {@code @EnableExperimentalNeo4jRepositories(basePackages="org.my.pkg")}.
*/
String[] value() default {};
/**
* Base packages to scan for annotated components. {@link #value()} is an alias for (and mutually exclusive with) this
* attribute. Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names.
*/
String[] basePackages() default {};
/**
* Base packages to scan for annotated components. {@link #value()} is an alias for (and mutually exclusive with) this
* attribute. Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names.
*/
String[] basePackages() default {};
/**
* Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components. The
* package of each class specified will be scanned. Consider creating a special no-op marker class or interface in
* each package that serves no purpose other than being referenced by this attribute.
*/
Class<?>[] basePackageClasses() default {};
/**
* Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components. The
* package of each class specified will be scanned. Consider creating a special no-op marker class or interface in
* each package that serves no purpose other than being referenced by this attribute.
*/
Class<?>[] basePackageClasses() default {};
/**
* Specifies which types are eligible for component scanning. Further narrows the set of candidate components from
* everything in {@link #basePackages()} to everything in the base packages that matches the given filter or filters.
*/
ComponentScan.Filter[] includeFilters() default {};
/**
* Specifies which types are eligible for component scanning. Further narrows the set of candidate components from
* everything in {@link #basePackages()} to everything in the base packages that matches the given filter or filters.
*/
ComponentScan.Filter[] includeFilters() default {};
/**
* Specifies which types are not eligible for component scanning.
*/
ComponentScan.Filter[] excludeFilters() default {};
/**
* Specifies which types are not eligible for component scanning.
*/
ComponentScan.Filter[] excludeFilters() default {};
/**
* Returns the postfix to be used when looking up custom repository implementations. Defaults to {@literal Impl}. So
* for a repository named {@code PersonRepository} the corresponding implementation class will be looked up scanning
* for {@code PersonRepositoryImpl}.
*/
String repositoryImplementationPostfix() default "Impl";
/**
* Returns the postfix to be used when looking up custom repository implementations. Defaults to {@literal Impl}. So
* for a repository named {@code PersonRepository} the corresponding implementation class will be looked up scanning
* for {@code PersonRepositoryImpl}.
*/
String repositoryImplementationPostfix() default "Impl";
/**
* Configures the location of where to find the Spring Data named queries properties file. Will default to
* {@code META-INFO/neo4j-named-queries.properties}.
*/
String namedQueriesLocation() default "";
/**
* Configures the location of where to find the Spring Data named queries properties file. Will default to
* {@code META-INFO/neo4j-named-queries.properties}.
*/
String namedQueriesLocation() default "";
/**
* Returns the key of the {@link QueryLookupStrategy} to be used for lookup queries for query methods. Defaults to
* {@link org.springframework.data.repository.query.QueryLookupStrategy.Key#CREATE_IF_NOT_FOUND}.
*/
QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND;
/**
* Returns the key of the {@link QueryLookupStrategy} to be used for lookup queries for query methods. Defaults to
* {@link org.springframework.data.repository.query.QueryLookupStrategy.Key#CREATE_IF_NOT_FOUND}.
*/
QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND;
/**
* Returns the {@link org.springframework.beans.factory.FactoryBean} class to be used for each repository instance. Defaults to
* {@link Neo4jRepositoryFactoryBean}.
*/
Class<?> repositoryFactoryBeanClass() default Neo4jRepositoryFactoryBean.class;
/**
* Returns the {@link org.springframework.beans.factory.FactoryBean} class to be used for each repository instance.
* Defaults to {@link Neo4jRepositoryFactoryBean}.
*/
Class<?> repositoryFactoryBeanClass() default Neo4jRepositoryFactoryBean.class;
/**
* Configure the repository base class to be used to create repository proxies for this particular configuration.
*
* @return
*/
Class<?> repositoryBaseClass() default DefaultRepositoryBaseClass.class;
/**
* Configure the repository base class to be used to create repository proxies for this particular configuration.
*
* @return
*/
Class<?> repositoryBaseClass() default DefaultRepositoryBaseClass.class;
/**
* Configures the name of the {@link SessionFactory} bean definition to be used to create repositories
* discovered through this annotation. Defaults to {@code sessionFactory}.
*/
String sessionFactoryRef() default "sessionFactory";
/**
* Configures the name of the {@link SessionFactory} bean definition to be used to create repositories discovered
* through this annotation. Defaults to {@code sessionFactory}.
*/
String sessionFactoryRef() default "sessionFactory";
/**
* Configures the name of the {@link PlatformTransactionManager} bean definition to be used to create repositories
* discovered through this annotation. Defaults to {@code transactionManager}.
*/
String transactionManagerRef() default "transactionManager";
/**
* Configures the name of the {@link PlatformTransactionManager} bean definition to be used to create repositories
* discovered through this annotation. Defaults to {@code transactionManager}.
*/
String transactionManagerRef() default "transactionManager";
/**
* Configures whether nested repository-interfaces (e.g. defined as inner classes) should be discovered by the
* repositories infrastructure.
*/
boolean considerNestedRepositories() default false;
/**
* Configures whether nested repository-interfaces (e.g. defined as inner classes) should be discovered by the
* repositories infrastructure.
*/
boolean considerNestedRepositories() default false;
/**
* Configures whether to enable default transactions for Spring Data Neo4j repositories. Defaults to {@literal true}. If
* disabled, repositories must be used behind a facade that's configuring transactions (e.g. using Spring's annotation
* driven transaction facilities) or repository methods have to be used to demarcate transactions.
*
* @return whether to enable default transactions, defaults to {@literal true}.
*/
boolean enableDefaultTransactions() default true;
/**
* Configures whether to enable default transactions for Spring Data Neo4j repositories. Defaults to {@literal true}.
* If disabled, repositories must be used behind a facade that's configuring transactions (e.g. using Spring's
* annotation driven transaction facilities) or repository methods have to be used to demarcate transactions.
*
* @return whether to enable default transactions, defaults to {@literal true}.
*/
boolean enableDefaultTransactions() default true;
}

View File

@@ -35,11 +35,11 @@ public class Neo4jAuditingEventListener extends EventListenerAdapter implements
* Creates a new {@link Neo4jAuditingEventListener} using the given {@link MappingContext} and {@link AuditingHandler}
* provided by the given {@link ObjectFactory}. This constructor does an additional registration to the
* {@link SessionFactory}. Therefore the {@link SessionFactory} must already be instantiated.
*
*
* @param auditingHandlerFactory must not be {@literal null}.
*/
public Neo4jAuditingEventListener(ObjectFactory<IsNewAwareAuditingHandler> auditingHandlerFactory,
SessionFactory sessionFactory) {
SessionFactory sessionFactory) {
Assert.notNull(auditingHandlerFactory, "IsNewAwareAuditingHandler must not be null!");
this.auditingHandlerFactory = auditingHandlerFactory;
@@ -50,7 +50,7 @@ public class Neo4jAuditingEventListener extends EventListenerAdapter implements
/**
* Constructor used for creating an instance in the {@link Neo4jAuditingRegistrar} to get registered in the session
* "manually". The registration is done within the {@link Neo4jAuditingBeanFactoryPostProcessor}.
*
*
* @param auditingHandlerFactory {@link AuditingHandler} to hook into the {@code preSave} phase for auditing.
*/
public Neo4jAuditingEventListener(ObjectFactory<IsNewAwareAuditingHandler> auditingHandlerFactory) {

View File

@@ -47,7 +47,8 @@ public class Neo4jAuditingRegistrar extends AuditingBeanDefinitionRegistrarSuppo
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Neo4jIsNewAwareAuditingHandler.class);
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(Neo4jMappingContextFactoryBean.class);
BeanDefinitionBuilder definition = BeanDefinitionBuilder
.genericBeanDefinition(Neo4jMappingContextFactoryBean.class);
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
builder.addConstructorArgValue(definition.getBeanDefinition());
@@ -56,7 +57,7 @@ public class Neo4jAuditingRegistrar extends AuditingBeanDefinitionRegistrarSuppo
@Override
protected void registerAuditListenerBeanDefinition(BeanDefinition auditingHandlerDefinition,
BeanDefinitionRegistry registry) {
BeanDefinitionRegistry registry) {
Assert.notNull(auditingHandlerDefinition, "BeanDefinition must not be null!");
Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");

View File

@@ -33,7 +33,8 @@ public class Neo4jIsNewAwareAuditingHandler extends IsNewAwareAuditingHandler {
private IsNewStrategyFactory isNewStrategyFactory;
public Neo4jIsNewAwareAuditingHandler(MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> mappingContext) {
public Neo4jIsNewAwareAuditingHandler(
MappingContext<? extends PersistentEntity<?, ?>, ? extends PersistentProperty<?>> mappingContext) {
this(new PersistentEntities(Collections.singletonList(mappingContext)));
}

View File

@@ -13,7 +13,6 @@
package org.springframework.data.neo4j.repository.config;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
@@ -28,8 +27,8 @@ import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
*
* @author Mark Angrish
*/
class Neo4jMappingContextFactoryBean extends AbstractFactoryBean<Neo4jMappingContext> implements
ApplicationContextAware {
class Neo4jMappingContextFactoryBean extends AbstractFactoryBean<Neo4jMappingContext>
implements ApplicationContextAware {
private ListableBeanFactory beanFactory;
@@ -52,9 +51,9 @@ class Neo4jMappingContextFactoryBean extends AbstractFactoryBean<Neo4jMappingCon
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
*/
* (non-Javadoc)
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
*/
@Override
protected Neo4jMappingContext createInstance() throws Exception {

View File

@@ -13,11 +13,11 @@
package org.springframework.data.neo4j.repository.config;
import java.lang.annotation.Annotation;
import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
import java.lang.annotation.Annotation;
/**
* @author Vince Bickers
* @author Mark Angrish

View File

@@ -86,6 +86,7 @@ public abstract class AbstractGraphRepositoryQuery implements RepositoryQuery {
/**
* Does the query returns an OGM specific object type that should get a special processing ?
*
* @return true is that's the case
*/
private boolean returnsOgmSpecificType() {

View File

@@ -30,7 +30,6 @@ import org.springframework.data.neo4j.annotation.QueryResult;
*/
class CustomResultConverter implements Converter<Object, Object> {
private final MetaData metaData;
private final Class returnedType;
@@ -48,8 +47,9 @@ class CustomResultConverter implements Converter<Object, Object> {
}
SingleUseEntityMapper mapper = new SingleUseEntityMapper(metaData, new EntityFactory(metaData));
if (returnedType.isInterface()) {
Class<?>[] interfaces = new Class<?>[]{returnedType};
return newProxyInstance(returnedType.getClassLoader(), interfaces, new QueryResultProxy((Map<String, Object>) source));
Class<?>[] interfaces = new Class<?>[] { returnedType };
return newProxyInstance(returnedType.getClassLoader(), interfaces,
new QueryResultProxy((Map<String, Object>) source));
}
return mapper.map(returnedType, (Map<String, Object>) source);
}

View File

@@ -24,13 +24,16 @@ import org.springframework.data.repository.query.ParameterAccessor;
public interface GraphParameterAccessor extends ParameterAccessor {
/**
* Gets the loading depth value of the {@link org.springframework.data.neo4j.annotation.Depth} annotated method parameter.
* Gets the loading depth value of the {@link org.springframework.data.neo4j.annotation.Depth} annotated method
* parameter.
*
* @return the depth value
*/
int getDepth();
/**
* Get OGM specific sort order translated from method parameters.
*
* @return The sort order
*/
SortOrder getOgmSort();

View File

@@ -61,8 +61,8 @@ public class GraphParameters extends Parameters<GraphParameters, GraphParameters
if (this.depthIndex == null && graphParameter.isDepthParameter()) {
this.depthIndex = graphParameter.getIndex();
} else if (graphParameter.isDepthParameter()) {
throw new IllegalStateException(String.format(
"Found multiple @Depth annotations on method %s! Only one allowed!", parameter.getMethod().toString()));
throw new IllegalStateException(String.format("Found multiple @Depth annotations on method %s! Only one allowed!",
parameter.getMethod().toString()));
}
return graphParameter;
@@ -98,8 +98,8 @@ public class GraphParameters extends Parameters<GraphParameters, GraphParameters
@Override
public boolean isSpecialParameter() {
return super.isSpecialParameter() || Distance.class.isAssignableFrom(getType())
|| parameter.getParameterAnnotation(Depth.class) != null
|| Distance.class.isAssignableFrom(getType()) || Point.class.isAssignableFrom(getType());
|| parameter.getParameterAnnotation(Depth.class) != null || Distance.class.isAssignableFrom(getType())
|| Point.class.isAssignableFrom(getType());
}
boolean isDepthParameter() {

View File

@@ -32,7 +32,8 @@ public class GraphParametersParameterAccessor extends ParametersParameterAccesso
/**
* Creates a new {@link ParametersParameterAccessor}.
* @param method must not be {@literal null}.
*
* @param method must not be {@literal null}.
* @param values must not be {@literal null}.
*/
public GraphParametersParameterAccessor(GraphQueryMethod method, Object[] values) {

View File

@@ -40,10 +40,10 @@ import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.util.Assert;
/**
* Classes intended to pilot query execution according to the type of the query.
* The type of the query is determined by looking at the result class of the method.
* @see AbstractGraphRepositoryQuery#getExecution(org.springframework.data.neo4j.repository.query.GraphParameterAccessor)
* Classes intended to pilot query execution according to the type of the query. The type of the query is determined by
* looking at the result class of the method.
*
* @see AbstractGraphRepositoryQuery#getExecution(org.springframework.data.neo4j.repository.query.GraphParameterAccessor)
* @author Nicolas Mervaillie
*/
public interface GraphQueryExecution {
@@ -75,7 +75,7 @@ public interface GraphQueryExecution {
}
}
Iterator<?> iterator = result.iterator();
if (! iterator.hasNext()) {
if (!iterator.hasNext()) {
return null;
}
Object ret = iterator.next();
@@ -144,9 +144,9 @@ public interface GraphQueryExecution {
List<?> result;
long count;
if (query.isFilterQuery()) {
result = (List<?>) session.loadAll(type, query.getFilters(), accessor.getOgmSort()
, query.getPagination(pageable, false), accessor.getDepth());
count = session.count(type, query.getFilters());
result = (List<?>) session.loadAll(type, query.getFilters(), accessor.getOgmSort(),
query.getPagination(pageable, false), accessor.getDepth());
count = session.count(type, query.getFilters());
} else {
if (type.getAnnotation(QueryResult.class) != null) {
result = (List<?>) session.query(query.getCypherQuery(pageable, false), query.getParameters()).queryResults();
@@ -185,8 +185,8 @@ public interface GraphQueryExecution {
List<?> result;
if (query.isFilterQuery()) {
// For a slice, need one extra result to determine if there is a next page
result = (List<?>) session.loadAll(type, query.getFilters(), accessor.getOgmSort()
, query.getPagination(pageable, true), accessor.getDepth());
result = (List<?>) session.loadAll(type, query.getFilters(), accessor.getOgmSort(),
query.getPagination(pageable, true), accessor.getDepth());
} else {
String cypherQuery = query.getCypherQuery(pageable, true);
if (type.getAnnotation(QueryResult.class) != null) {

View File

@@ -33,107 +33,106 @@ import org.springframework.util.StringUtils;
*/
public class GraphQueryMethod extends QueryMethod {
private final Method method;
private final Query queryAnnotation;
private final Integer queryDepthParamIndex;
private final Method method;
private final Query queryAnnotation;
private final Integer queryDepthParamIndex;
public GraphQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
super(method, metadata, factory);
this.method = method;
this.queryAnnotation = method.getAnnotation(Query.class);
this.queryDepthParamIndex = getQueryDepthParamIndex(method);
Integer queryDepth = getStaticQueryDepth(method);
if (queryDepth !=null && queryDepthParamIndex!=null) {
throw new IllegalArgumentException(method.getName() + " cannot have both a method @Depth and a parameter @Depth");
}
public GraphQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
super(method, metadata, factory);
this.method = method;
this.queryAnnotation = method.getAnnotation(Query.class);
this.queryDepthParamIndex = getQueryDepthParamIndex(method);
Integer queryDepth = getStaticQueryDepth(method);
if (queryDepth != null && queryDepthParamIndex != null) {
throw new IllegalArgumentException(method.getName() + " cannot have both a method @Depth and a parameter @Depth");
}
}
}
@Override
protected Parameters<?, ?> createParameters(Method method) {
return new GraphParameters(method);
}
@Override
protected Parameters<?, ?> createParameters(Method method) {
return new GraphParameters(method);
}
@Override
public GraphParameters getParameters() {
return (GraphParameters) super.getParameters();
}
@Override
public GraphParameters getParameters() {
return (GraphParameters) super.getParameters();
}
public String getQuery() {
return queryAnnotation.value();
}
public String getQuery() {
return queryAnnotation.value();
}
public Method getMethod() {
return method;
}
public Method getMethod() {
return method;
}
/**
* Returns the name of the named query this method belongs to.
*
* @return
*/
public String getNamedQueryName() {
return String.format("%s.%s", getDomainClass().getSimpleName(), method.getName());
}
/**
* Returns the name of the named query this method belongs to.
*
* @return
*/
public String getNamedQueryName() {
return String.format("%s.%s", getDomainClass().getSimpleName(), method.getName());
}
public Integer getQueryDepthParamIndex() {
return queryDepthParamIndex;
}
public Integer getQueryDepthParamIndex() {
return queryDepthParamIndex;
}
private Integer getQueryDepthParamIndex(Method method) {
Annotation[][] annotations = method.getParameterAnnotations();
for (int i = 0; i < annotations.length; i++) {
if (annotations[i].length > 0) {
for (Annotation annotation : annotations[i]) {
if (annotation.annotationType() == Depth.class) {
if (method.getParameterTypes()[i] == Integer.class || method.getParameterTypes()[i] == int.class) {
return i;
}
else {
throw new IllegalArgumentException("Depth parameter in " + method.getName() + " must be an integer");
}
}
}
}
}
/*
//Java 8 only
Parameter[] parameters = method.getParameters();
for (int i = 0; i < method.getParameterCount(); i++) {
if (parameters[i].isAnnotationPresent(Depth.class)) {
if (parameters[i].getType() == Integer.class || parameters[i].getType() == int.class) {
return i;
}
else {
throw new IllegalArgumentException("Depth parameter in " + method.getName() + " must be an integer");
}
}
}*/
return null;
}
private Integer getQueryDepthParamIndex(Method method) {
Annotation[][] annotations = method.getParameterAnnotations();
for (int i = 0; i < annotations.length; i++) {
if (annotations[i].length > 0) {
for (Annotation annotation : annotations[i]) {
if (annotation.annotationType() == Depth.class) {
if (method.getParameterTypes()[i] == Integer.class || method.getParameterTypes()[i] == int.class) {
return i;
} else {
throw new IllegalArgumentException("Depth parameter in " + method.getName() + " must be an integer");
}
}
}
}
}
/*
//Java 8 only
Parameter[] parameters = method.getParameters();
for (int i = 0; i < method.getParameterCount(); i++) {
if (parameters[i].isAnnotationPresent(Depth.class)) {
if (parameters[i].getType() == Integer.class || parameters[i].getType() == int.class) {
return i;
}
else {
throw new IllegalArgumentException("Depth parameter in " + method.getName() + " must be an integer");
}
}
}*/
return null;
}
private Integer getStaticQueryDepth(Method method) {
if (method.isAnnotationPresent(Depth.class)) {
return method.getAnnotation(Depth.class).value();
}
return null;
}
private Integer getStaticQueryDepth(Method method) {
if (method.isAnnotationPresent(Depth.class)) {
return method.getAnnotation(Depth.class).value();
}
return null;
}
public String getCountQueryString() {
return queryAnnotation != null ? queryAnnotation.countQuery() : null;
}
public String getCountQueryString() {
return queryAnnotation != null ? queryAnnotation.countQuery() : null;
}
public boolean hasAnnotatedQuery() {
return getAnnotatedQuery() != null;
}
public boolean hasAnnotatedQuery() {
return getAnnotatedQuery() != null;
}
private String getAnnotatedQuery() {
private String getAnnotatedQuery() {
String query = (String) AnnotationUtils.getValue(getQueryAnnotation());
return StringUtils.hasText(query) ? query : null;
}
String query = (String) AnnotationUtils.getValue(getQueryAnnotation());
return StringUtils.hasText(query) ? query : null;
}
private Query getQueryAnnotation() {
return AnnotatedElementUtils.findMergedAnnotation(method, Query.class);
}
private Query getQueryAnnotation() {
return AnnotatedElementUtils.findMergedAnnotation(method, Query.class);
}
}

View File

@@ -26,7 +26,6 @@
package org.springframework.data.neo4j.repository.query;
import java.util.HashMap;
import java.util.Map;
@@ -40,7 +39,6 @@ import org.springframework.data.repository.query.Parameters;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.ResultProcessor;
/**
* Specialisation of {@link RepositoryQuery} that handles mapping to object annotated with <code>&#064;Query</code>.
*
@@ -76,8 +74,9 @@ public class GraphRepositoryQuery extends AbstractGraphRepositoryQuery {
Object result = getExecution(accessor).execute(query, processor.getReturnedType().getReturnedType());
return Result.class.equals(returnType)
? result : processor.processResult(result, new CustomResultConverter(getMetaData(), processor.getReturnedType().getReturnedType()));
return Result.class.equals(returnType) ? result
: processor.processResult(result,
new CustomResultConverter(getMetaData(), processor.getReturnedType().getReturnedType()));
}
protected Query getQuery(Object[] parameters) {
@@ -113,9 +112,9 @@ public class GraphRepositoryQuery extends AbstractGraphRepositoryQuery {
private Object getParameterValue(Object parameter) {
//The parameter might be an entity, try to resolve its id
// The parameter might be an entity, try to resolve its id
Object parameterValue = session.resolveGraphIdFor(parameter);
if (parameterValue == null) { //Either not an entity or not persisted
if (parameterValue == null) { // Either not an entity or not persisted
parameterValue = parameter;
}
return parameterValue;

View File

@@ -37,9 +37,8 @@ import org.springframework.data.neo4j.util.PagingAndSortingUtils;
import org.springframework.util.Assert;
/**
* Represents an OGM query. Can hold either cypher queries or filter definitions.
* Also in charge of adding pagination / sort to the string based queries as OGM does not support
* pagination and sort on those.
* Represents an OGM query. Can hold either cypher queries or filter definitions. Also in charge of adding pagination /
* sort to the string based queries as OGM does not support pagination and sort on those.
*
* @author Nicolas Mervaillie
*/
@@ -102,7 +101,7 @@ public class Query {
sort = pageable.getSort();
}
if (sort != Sort.unsorted()) {
//Custom queries in the OGM do not support pageable
// Custom queries in the OGM do not support pageable
result = addSorting(result, sort);
}
result = addPaging(result, pageable, forSlicing);
@@ -110,7 +109,7 @@ public class Query {
}
public String getCypherQuery(Sort sort) {
//Custom queries in the OGM do not support pageable
// Custom queries in the OGM do not support pageable
String result = cypherQuery;
if (sort != Sort.unsorted()) {
result = addSorting(cypherQuery, sort);
@@ -119,7 +118,7 @@ public class Query {
}
private String addPaging(String cypherQuery, Pageable pageable, boolean forSlicing) {
//Custom queries in the OGM do not support pageable
// Custom queries in the OGM do not support pageable
cypherQuery = formatBaseQuery(cypherQuery);
cypherQuery = cypherQuery + SKIP_LIMIT;
parameters.put(SKIP, pageable.getPageNumber() * pageable.getPageSize());
@@ -163,7 +162,7 @@ public class Query {
}
public Pagination getPagination(Pageable pageable, boolean forSlicing) {
Pagination pagination = new Pagination(pageable.getPageNumber(), pageable.getPageSize() + ((forSlicing)?1:0));
Pagination pagination = new Pagination(pageable.getPageNumber(), pageable.getPageSize() + ((forSlicing) ? 1 : 0));
pagination.setOffset(pageable.getPageNumber() * pageable.getPageSize());
return pagination;
}

View File

@@ -13,17 +13,17 @@
package org.springframework.data.neo4j.repository.query;
import org.neo4j.ogm.annotation.Property;
import org.neo4j.ogm.session.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.neo4j.ogm.annotation.Property;
import org.neo4j.ogm.session.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Method {@link InvocationHandler} used for proxy objects that implement arbitrary interfaces annotated with
* <code>&#064;QueryResult</code>.
@@ -32,41 +32,41 @@ import java.util.regex.Pattern;
*/
class QueryResultProxy implements InvocationHandler {
private static final Logger log = LoggerFactory.getLogger(QueryResultProxy.class);
private static final Logger log = LoggerFactory.getLogger(QueryResultProxy.class);
private static final Pattern beanGetterPattern = Pattern.compile("^(is|get)(\\w+)");
private static final Pattern beanGetterPattern = Pattern.compile("^(is|get)(\\w+)");
private final Map<String, ?> data;
private final Map<String, ?> data;
QueryResultProxy(Map<String, ?> queryResults) {
this.data = queryResults;
}
QueryResultProxy(Map<String, ?> queryResults) {
this.data = queryResults;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (isNotTraditionalGetter(method)) {
log.warn("QueryResult interface method " + method.getName()
+ " doesn't appear to be a getter and therefore may not return the correct result.");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (isNotTraditionalGetter(method)) {
log.warn("QueryResult interface method " + method.getName()
+ " doesn't appear to be a getter and therefore may not return the correct result.");
}
if (method.isAnnotationPresent(Property.class)) {
Property annotation = method.getAnnotation(Property.class);
return Utils.coerceTypes(method.getReturnType(), data.get(annotation.name()));
}
if (method.isAnnotationPresent(Property.class)) {
Property annotation = method.getAnnotation(Property.class);
return Utils.coerceTypes(method.getReturnType(), data.get(annotation.name()));
}
Matcher matcher = beanGetterPattern.matcher(method.getName());
if (matcher.matches()) {
String propertyKey = matcher.group(2);
propertyKey = propertyKey.substring(0, 1).toLowerCase().concat(propertyKey.substring(1));
return Utils.coerceTypes(method.getReturnType(),data.get(propertyKey));
}
Matcher matcher = beanGetterPattern.matcher(method.getName());
if (matcher.matches()) {
String propertyKey = matcher.group(2);
propertyKey = propertyKey.substring(0, 1).toLowerCase().concat(propertyKey.substring(1));
return Utils.coerceTypes(method.getReturnType(), data.get(propertyKey));
}
return Utils.coerceTypes(method.getReturnType(), data.get(method.getName()));
}
return Utils.coerceTypes(method.getReturnType(), data.get(method.getName()));
}
private boolean isNotTraditionalGetter(Method method) {
return method.getParameterTypes().length != 0 || Void.class.equals(method.getReturnType())
|| (!method.getName().startsWith("get") && !method.getName().startsWith("is"));
}
private boolean isNotTraditionalGetter(Method method) {
return method.getParameterTypes().length != 0 || Void.class.equals(method.getReturnType())
|| (!method.getName().startsWith("get") && !method.getName().startsWith("is"));
}
}

View File

@@ -12,11 +12,21 @@
*/
package org.springframework.data.neo4j.repository.query.derived;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import org.neo4j.ogm.cypher.BooleanOperator;
import org.neo4j.ogm.cypher.Filter;
import org.springframework.data.neo4j.repository.query.derived.builder.*;
import org.springframework.data.neo4j.repository.query.derived.builder.BetweenComparisonBuilder;
import org.springframework.data.neo4j.repository.query.derived.builder.BooleanComparisonBuilder;
import org.springframework.data.neo4j.repository.query.derived.builder.DistanceComparisonBuilder;
import org.springframework.data.neo4j.repository.query.derived.builder.ExistsFilterBuilder;
import org.springframework.data.neo4j.repository.query.derived.builder.FilterBuilder;
import org.springframework.data.neo4j.repository.query.derived.builder.IsNullFilterBuilder;
import org.springframework.data.neo4j.repository.query.derived.builder.PropertyComparisonBuilder;
import org.springframework.data.repository.query.parser.Part;
/**
@@ -28,64 +38,64 @@ import org.springframework.data.repository.query.parser.Part;
*/
public class CypherFinderQuery implements DerivedQueryDefinition {
private Class<?> entityType;
private Part basePart;
private List<FilterBuilder> filterBuilders = new ArrayList<>();
private Class<?> entityType;
private Part basePart;
private List<FilterBuilder> filterBuilders = new ArrayList<>();
CypherFinderQuery(Class<?> entityType, Part basePart) {
this.entityType = entityType;
this.basePart = basePart;
}
CypherFinderQuery(Class<?> entityType, Part basePart) {
this.entityType = entityType;
this.basePart = basePart;
}
@Override
public Part getBasePart() { //because the OR is handled in a weird way. Luanne, explain better
return basePart;
}
@Override
public Part getBasePart() { // because the OR is handled in a weird way. Luanne, explain better
return basePart;
}
@Override
public List<Filter> getFilters(Map<Integer, Object> params) {
@Override
public List<Filter> getFilters(Map<Integer, Object> params) {
// buiding a stack of parameter values, so that the builders can pull them
// according to their needs (zero, one or more parameters)
// avoids to manage a current parameter index state here.
Stack<Object> parametersStack = new Stack<>();
if (!params.isEmpty()) {
Integer maxParameterIndex = Collections.max(params.keySet());
for (int i = 0; i <= maxParameterIndex; i++) {
parametersStack.add(0, params.get(i));
}
}
// buiding a stack of parameter values, so that the builders can pull them
// according to their needs (zero, one or more parameters)
// avoids to manage a current parameter index state here.
Stack<Object> parametersStack = new Stack<>();
if (!params.isEmpty()) {
Integer maxParameterIndex = Collections.max(params.keySet());
for (int i = 0; i <= maxParameterIndex; i++) {
parametersStack.add(0, params.get(i));
}
}
List<Filter> filters = new ArrayList<>();
for (FilterBuilder filterBuilder : filterBuilders) {
filters.addAll(filterBuilder.build(parametersStack));
}
return filters;
}
List<Filter> filters = new ArrayList<>();
for (FilterBuilder filterBuilder : filterBuilders) {
filters.addAll(filterBuilder.build(parametersStack));
}
return filters;
}
@Override
public void addPart(Part part, BooleanOperator booleanOperator) {
@Override
public void addPart(Part part, BooleanOperator booleanOperator) {
FilterBuilder builder = builderForPart(part, booleanOperator);
filterBuilders.add(builder);
}
FilterBuilder builder = builderForPart(part, booleanOperator);
filterBuilders.add(builder);
}
private FilterBuilder builderForPart(Part part, BooleanOperator booleanOperator) {
switch (part.getType()) {
case NEAR:
return new DistanceComparisonBuilder(part, booleanOperator, entityType);
case BETWEEN:
return new BetweenComparisonBuilder(part, booleanOperator, entityType);
case IS_NULL:
case IS_NOT_NULL:
return new IsNullFilterBuilder(part, booleanOperator, entityType);
case EXISTS:
return new ExistsFilterBuilder(part, booleanOperator, entityType);
case TRUE:
case FALSE:
return new BooleanComparisonBuilder(part, booleanOperator, entityType);
default:
return new PropertyComparisonBuilder(part, booleanOperator, entityType);
}
}
private FilterBuilder builderForPart(Part part, BooleanOperator booleanOperator) {
switch (part.getType()) {
case NEAR:
return new DistanceComparisonBuilder(part, booleanOperator, entityType);
case BETWEEN:
return new BetweenComparisonBuilder(part, booleanOperator, entityType);
case IS_NULL:
case IS_NOT_NULL:
return new IsNullFilterBuilder(part, booleanOperator, entityType);
case EXISTS:
return new ExistsFilterBuilder(part, booleanOperator, entityType);
case TRUE:
case FALSE:
return new BooleanComparisonBuilder(part, booleanOperator, entityType);
default:
return new PropertyComparisonBuilder(part, booleanOperator, entityType);
}
}
}

View File

@@ -95,7 +95,8 @@ public class DerivedGraphRepositoryQuery extends AbstractGraphRepositoryQuery {
}
/**
* Sets values from parameters supplied by the finder on {@link org.neo4j.ogm.cypher.Filter} built by the {@link GraphQueryMethod}
* Sets values from parameters supplied by the finder on {@link org.neo4j.ogm.cypher.Filter} built by the
* {@link GraphQueryMethod}
*
* @param parameters parameter values supplied by the finder method
* @return List of Parameter with values set

View File

@@ -31,6 +31,7 @@ public class DerivedQueryBuilder {
/**
* Add a part as a parameter to the graph query.
*
* @param part the Part to be added
* @param booleanOperator the {@link BooleanOperator} to be used when appending the parameter to the query.
*/
@@ -40,6 +41,7 @@ public class DerivedQueryBuilder {
/**
* Add criteria from an intermediate builder to the query
*
* @param fromBuilder the intermediate builder
* @param booleanOperator the {@link BooleanOperator} to be used when appending the criteria to the query
*/
@@ -49,6 +51,7 @@ public class DerivedQueryBuilder {
/**
* Builds the final query
*
* @return the final query
*/
public DerivedQueryDefinition buildQuery() {

View File

@@ -11,17 +11,16 @@
*
*/
package org.springframework.data.neo4j.repository.query.derived;
import java.util.Iterator;
import org.neo4j.ogm.cypher.BooleanOperator;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.data.repository.query.parser.Part;
import org.springframework.data.repository.query.parser.PartTree;
import java.util.Iterator;
/**
* An {@link AbstractQueryCreator} that builds a graph query.
*

View File

@@ -21,9 +21,8 @@ import org.neo4j.ogm.cypher.Filter;
import org.springframework.data.repository.query.parser.Part;
/**
* The graph query created based on a derived query.
* The graph query created based on a derived query. /**
*
/**
* @author Luanne Misquitta
* @author Nicolas Mervaillie
*/
@@ -31,19 +30,22 @@ public interface DerivedQueryDefinition {
/**
* Add a part as a parameter to the graph query.
* @param part the Part to be added
*
* @param part the Part to be added
* @param booleanOperator the {@link BooleanOperator} to be used when appending the parameter to the query.
*/
void addPart(Part part, BooleanOperator booleanOperator);
/**
* Get the base part i.e. the first parameter of the graph query.
*
* @return Part representing the base of the query.
*/
Part getBasePart();
/**
* Gets all cypher filters for this query
*
* @return The OGM filters with bound parameter values
*/
List<Filter> getFilters(Map<Integer, Object> params);

View File

@@ -11,7 +11,6 @@
*
*/
package org.springframework.data.neo4j.repository.query.derived.builder;
import static org.springframework.data.repository.query.parser.Part.Type.*;

View File

@@ -11,7 +11,6 @@
*
*/
package org.springframework.data.neo4j.repository.query.derived.builder;
import java.util.Collections;
@@ -54,7 +53,8 @@ public class DistanceComparisonBuilder extends FilterBuilder {
distance = (Distance) secondArg;
point = (Point) firstArg;
} else {
throw new IllegalArgumentException("findNear requires an argument of type Distance and an argument of type Point");
throw new IllegalArgumentException(
"findNear requires an argument of type Distance and an argument of type Point");
}
double meters;
@@ -66,7 +66,8 @@ public class DistanceComparisonBuilder extends FilterBuilder {
meters = distance.getValue();
}
DistanceFromPoint distanceFromPoint = new DistanceFromPoint(point.getX(), point.getY(), distance.getValue() * meters);
DistanceFromPoint distanceFromPoint = new DistanceFromPoint(point.getX(), point.getY(),
distance.getValue() * meters);
DistanceComparison distanceComparison = new DistanceComparison(distanceFromPoint);
Filter filter = new Filter(distanceComparison, ComparisonOperator.LESS_THAN);

View File

@@ -1,6 +1,5 @@
package org.springframework.data.neo4j.repository.query.derived.builder;
import java.util.Collections;
import java.util.List;
import java.util.Stack;

View File

@@ -11,7 +11,6 @@
*
*/
package org.springframework.data.neo4j.repository.query.derived.builder;
import static org.springframework.data.repository.query.parser.Part.Type.*;
@@ -31,19 +30,19 @@ import org.springframework.data.repository.query.parser.Part;
*/
public class IsNullFilterBuilder extends FilterBuilder {
public IsNullFilterBuilder(Part part, BooleanOperator booleanOperator, Class<?> entityType) {
super(part, booleanOperator, entityType);
}
public IsNullFilterBuilder(Part part, BooleanOperator booleanOperator, Class<?> entityType) {
super(part, booleanOperator, entityType);
}
@Override
public List<Filter> build(Stack<Object> params) {
Filter filter = new Filter(propertyName(), ComparisonOperator.IS_NULL);
filter.setOwnerEntityType(entityType);
filter.setBooleanOperator(booleanOperator);
filter.setNegated(isNegated() || part.getType() == IS_NOT_NULL);
setNestedAttributes(part, filter);
@Override
public List<Filter> build(Stack<Object> params) {
Filter filter = new Filter(propertyName(), ComparisonOperator.IS_NULL);
filter.setOwnerEntityType(entityType);
filter.setBooleanOperator(booleanOperator);
filter.setNegated(isNegated() || part.getType() == IS_NOT_NULL);
setNestedAttributes(part, filter);
return Collections.singletonList(filter);
}
return Collections.singletonList(filter);
}
}

View File

@@ -45,7 +45,6 @@ public class PropertyComparisonBuilder extends FilterBuilder {
return Collections.singletonList(filter);
}
private ComparisonOperator convertToComparisonOperator(Part.Type type) {
switch (type) {
case AFTER:

View File

@@ -13,55 +13,52 @@
package org.springframework.data.neo4j.repository.support;
import org.neo4j.ogm.metadata.MetaData;
import java.io.Serializable;
import org.neo4j.ogm.metadata.ClassInfo;
import org.neo4j.ogm.metadata.FieldInfo;
import org.neo4j.ogm.metadata.reflect.EntityAccessManager;
import org.neo4j.ogm.metadata.MetaData;
import org.springframework.data.repository.core.support.AbstractEntityInformation;
import java.io.Serializable;
import java.util.Optional;
/**
* @author Mark Angrish
* @author Mark Paluch
*/
public class GraphEntityInformation<T, ID extends Serializable> extends AbstractEntityInformation<T, ID> {
private final MetaData metaData;
private final MetaData metaData;
public GraphEntityInformation(MetaData metaData, Class<T> type) {
super(type);
this.metaData = metaData;
}
public GraphEntityInformation(MetaData metaData, Class<T> type) {
super(type);
this.metaData = metaData;
}
@Override
@SuppressWarnings("unchecked")
public ID getId(T entity) {
final ClassInfo classInfo = metaData.classInfo(getJavaType().getName());
final FieldInfo primaryIndex = classInfo.primaryIndexField();
public ID getId(T entity) {
final ClassInfo classInfo = metaData.classInfo(getJavaType().getName());
final FieldInfo primaryIndex = classInfo.primaryIndexField();
return (ID) getId(entity, classInfo, primaryIndex);
}
return (ID) getId(entity, classInfo, primaryIndex);
}
private Object getId(T entity, ClassInfo classInfo, FieldInfo primaryIndex) {
if (primaryIndex != null) {
return classInfo.propertyField(primaryIndex.getName()).readProperty(entity);
}
else {
return classInfo.propertyField(classInfo.identityField().getName()).readProperty(entity);
}
}
private Object getId(T entity, ClassInfo classInfo, FieldInfo primaryIndex) {
if (primaryIndex != null) {
return classInfo.propertyField(primaryIndex.getName()).readProperty(entity);
} else {
return classInfo.propertyField(classInfo.identityField().getName()).readProperty(entity);
}
}
@Override
@Override
@SuppressWarnings("unchecked")
public Class<ID> getIdType() {
final FieldInfo primaryIndex = metaData.classInfo(getJavaType().getName()).primaryIndexField();
public Class<ID> getIdType() {
final FieldInfo primaryIndex = metaData.classInfo(getJavaType().getName()).primaryIndexField();
if (primaryIndex != null) {
return (Class<ID>) primaryIndex.convertedType();
}
return (Class<ID>) Long.class;
}
if (primaryIndex != null) {
return (Class<ID>) primaryIndex.convertedType();
}
return (Class<ID>) Long.class;
}
}

View File

@@ -13,7 +13,6 @@
package org.springframework.data.neo4j.repository.support;
import java.io.Serializable;
import java.util.Optional;
import org.neo4j.ogm.session.Neo4jSession;
@@ -58,7 +57,7 @@ public class Neo4jRepositoryFactory extends RepositoryFactorySupport {
public <T, ID> EntityInformation<T, ID> getEntityInformation(Class<T> type) {
Assert.notNull(type, "Domain class must not be null!");
Assert.notNull(session, "Session must not be null!");
return new GraphEntityInformation(((Neo4jSession)session).metaData(), type);
return new GraphEntityInformation(((Neo4jSession) session).metaData(), type);
}
@Override
@@ -73,7 +72,7 @@ public class Neo4jRepositoryFactory extends RepositoryFactorySupport {
@Override
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(QueryLookupStrategy.Key key,
EvaluationContextProvider evaluationContextProvider) {
EvaluationContextProvider evaluationContextProvider) {
return Optional.of(new GraphQueryLookupStrategy(session));
}
}

View File

@@ -23,7 +23,6 @@ import org.springframework.data.repository.core.support.RepositoryFactorySupport
import org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport;
import org.springframework.util.Assert;
/**
* Special adapter for Springs {@link org.springframework.beans.factory.FactoryBean} interface to allow easy setup of
* repository factories via Spring configuration.
@@ -33,13 +32,14 @@ import org.springframework.util.Assert;
* @author Luanne Misquitta
* @author Mark Angrish
*/
public class Neo4jRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> {
public class Neo4jRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> {
private Session session;
/**
* Creates a new {@link Neo4jRepositoryFactoryBean} for the given repository interface.
*
*
* @param repositoryInterface must not be {@literal null}.
*/
public Neo4jRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
@@ -81,5 +81,3 @@ public class Neo4jRepositoryFactoryBean<T extends Repository<S, ID>, S, ID exten
return new Neo4jRepositoryFactory(session);
}
}

View File

@@ -36,7 +36,6 @@ import org.springframework.util.Assert;
* you a more sophisticated interface than the plain {@link Session} .
*
* @param <T> the type of the entity to handle
*
* @author Vince Bickers
* @author Luanne Misquitta
* @author Mark Angrish
@@ -190,8 +189,8 @@ public class SimpleNeo4jRepository<T, ID extends Serializable> implements Neo4jR
@Override
public Page<T> findAll(Pageable pageable, int depth) {
Collection<T> data = session.loadAll(clazz, PagingAndSortingUtils.convert(pageable.getSort())
, new Pagination(pageable.getPageNumber(), pageable.getPageSize()), depth);
Collection<T> data = session.loadAll(clazz, PagingAndSortingUtils.convert(pageable.getSort()),
new Pagination(pageable.getPageNumber(), pageable.getPageSize()), depth);
return updatePage(pageable, new ArrayList<>(data));
}

View File

@@ -13,7 +13,6 @@
package org.springframework.data.neo4j.transaction;
import static java.util.Collections.*;
import java.util.Collection;
@@ -44,24 +43,22 @@ import org.springframework.transaction.support.ResourceTransactionManager;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* {@link PlatformTransactionManager} implementation
* for a single Neo4j OGM {@link SessionFactory}. Binds a Neo4j OGM
* Session from the specified factory to the thread, potentially allowing for
* one thread-bound Session per factory. {@link SharedSessionCreator}
* is aware of thread-bound session and participates
* in such transactions automatically. It is required for Neo4j OGM access code
* supporting this transaction management mechanism.
* <p>This transaction manager is appropriate for applications that use a single
* Neo4j OGM SessionFactory for transactional data access. JTA (usually through
* {@link org.springframework.transaction.jta.JtaTransactionManager}) has not been tested
* or considered at the moment.
* <p>This transaction manager does not support nested transactions or
* requires new propagation.
* {@link PlatformTransactionManager} implementation for a single Neo4j OGM {@link SessionFactory}. Binds a Neo4j OGM
* Session from the specified factory to the thread, potentially allowing for one thread-bound Session per factory.
* {@link SharedSessionCreator} is aware of thread-bound session and participates in such transactions automatically. It
* is required for Neo4j OGM access code supporting this transaction management mechanism.
* <p>
* This transaction manager is appropriate for applications that use a single Neo4j OGM SessionFactory for transactional
* data access. JTA (usually through {@link org.springframework.transaction.jta.JtaTransactionManager}) has not been
* tested or considered at the moment.
* <p>
* This transaction manager does not support nested transactions or requires new propagation.
*
* @author Mark Angrish
* @see #setSessionFactory
*/
public class Neo4jTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(Neo4jTransactionManager.class);
@@ -70,7 +67,8 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
/**
* Create a new Neo4jTransactionManager instance.
* <p>An SessionFactory has to be set to be able to use it.
* <p>
* An SessionFactory has to be set to be able to use it.
*
* @see #setSessionFactory(SessionFactory)
*/
@@ -78,7 +76,6 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
setTransactionSynchronization(SYNCHRONIZATION_ON_ACTUAL_TRANSACTION);
}
/**
* Create a new Neo4jTransactionManager instance.
*
@@ -89,17 +86,16 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
this.sessionFactory = sessionFactory;
}
/**
* Set the SessionFactory that this instance should manage transactions for.
* <p>By default, a default SessionFactory will be retrieved by finding a
* single unique bean of type SessionFactory in the containing BeanFactory.
* <p>
* By default, a default SessionFactory will be retrieved by finding a single unique bean of type SessionFactory in
* the containing BeanFactory.
*/
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
/**
* Return the SessionFactory that this instance should manage transactions for.
*/
@@ -107,7 +103,6 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
return this.sessionFactory;
}
/**
* Retrieves a default SessionFactory bean.
*/
@@ -124,7 +119,6 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
}
}
@Override
public void afterPropertiesSet() throws Exception {
if (getSessionFactory() == null) {
@@ -132,13 +126,11 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
}
}
@Override
public Object getResourceFactory() {
return getSessionFactory();
}
@Override
protected Object doGetTransaction() {
Neo4jTransactionObject txObject = new Neo4jTransactionObject();
@@ -146,28 +138,24 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
if (sessionHolder != null) {
if (logger.isDebugEnabled()) {
logger.debug("Found thread-bound Session [" + sessionHolder.getSession() +
"] for Neo4j OGM transaction");
logger.debug("Found thread-bound Session [" + sessionHolder.getSession() + "] for Neo4j OGM transaction");
}
txObject.setSessionHolder(sessionHolder, false);
}
return txObject;
}
@Override
protected boolean isExistingTransaction(Object transaction) {
return ((Neo4jTransactionObject) transaction).hasTransaction();
}
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException {
Neo4jTransactionObject txObject = (Neo4jTransactionObject) transaction;
try {
if (txObject.getSessionHolder() == null ||
txObject.getSessionHolder().isSynchronizedWithTransaction()) {
if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
Session session = sessionFactory.openSession();
if (logger.isDebugEnabled()) {
logger.debug("Opened new Session [" + session + "] for Neo4j OGM transaction");
@@ -184,8 +172,7 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
}
if (definition.getPropagationBehavior() != TransactionDefinition.PROPAGATION_REQUIRED) {
throw new IllegalTransactionStateException(
"Neo4jTransactionManager only supports 'required' propagation.");
throw new IllegalTransactionStateException("Neo4jTransactionManager only supports 'required' propagation.");
}
Transaction.Type type = getTransactionType(definition, txObject);
@@ -243,10 +230,8 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
}
}
/**
* Close the current transaction's Session.
* Called after a transaction begin attempt failed.
* Close the current transaction's Session. Called after a transaction begin attempt failed.
*
* @param txObject the current transaction
*/
@@ -267,17 +252,14 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
}
}
@Override
protected Object doSuspend(Object transaction) {
Neo4jTransactionObject txObject = (Neo4jTransactionObject) transaction;
txObject.setSessionHolder(null, false);
SessionHolder sessionHolder = (SessionHolder)
TransactionSynchronizationManager.unbindResource(getSessionFactory());
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(getSessionFactory());
return new SuspendedResourcesHolder(sessionHolder);
}
@Override
protected void doResume(Object transaction, Object suspendedResources) {
SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder) suspendedResources;
@@ -286,11 +268,9 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
// -> can be safely removed, will be closed on transaction completion.
TransactionSynchronizationManager.unbindResource(getSessionFactory());
}
TransactionSynchronizationManager.bindResource(
getSessionFactory(), resourcesHolder.getSessionHolder());
TransactionSynchronizationManager.bindResource(getSessionFactory(), resourcesHolder.getSessionHolder());
}
@Override
protected void doCommit(DefaultTransactionStatus status) {
@@ -326,7 +306,6 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
}
}
@Override
protected void doRollback(DefaultTransactionStatus status) {
Neo4jTransactionObject txObject = (Neo4jTransactionObject) status.getTransaction();
@@ -352,18 +331,16 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
}
}
@Override
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
Neo4jTransactionObject txObject = (Neo4jTransactionObject) status.getTransaction();
if (status.isDebug()) {
logger.debug("Setting Neo4j OGM transaction on Session [" +
txObject.getSessionHolder().getSession() + "] rollback-only");
logger.debug(
"Setting Neo4j OGM transaction on Session [" + txObject.getSessionHolder().getSession() + "] rollback-only");
}
status.setRollbackOnly();
}
@Override
protected void doCleanupAfterCompletion(Object transaction) {
Neo4jTransactionObject txObject = (Neo4jTransactionObject) transaction;
@@ -395,8 +372,7 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
}
/**
* Neo4j OGM transaction object, representing a SessionHolder.
* Used as transaction object by Neo4jTransactionManager.
* Neo4j OGM transaction object, representing a SessionHolder. Used as transaction object by Neo4jTransactionManager.
*/
private static class Neo4jTransactionObject {
@@ -406,8 +382,7 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
private Transaction transactionData;
void setSessionHolder(
SessionHolder sessionHolder, boolean newSessionHolder) {
void setSessionHolder(SessionHolder sessionHolder, boolean newSessionHolder) {
this.sessionHolder = sessionHolder;
this.newSessionHolder = newSessionHolder;
}
@@ -435,8 +410,7 @@ public class Neo4jTransactionManager extends AbstractPlatformTransactionManager
}
/**
* Holder for suspended resources.
* Used internally by {@code doSuspend} and {@code doResume}.
* Holder for suspended resources. Used internally by {@code doSuspend} and {@code doResume}.
*/
private static class SuspendedResourcesHolder {

View File

@@ -46,10 +46,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
import org.springframework.util.Assert;
/**
* Helper class featuring methods for Neo4j OGM Session handling,
* allowing for reuse of Session instances within transactions.
* Also provides support for exception translation.
* <p>Mainly intended for internal use within the framework.
* Helper class featuring methods for Neo4j OGM Session handling, allowing for reuse of Session instances within
* transactions. Also provides support for exception translation.
* <p>
* Mainly intended for internal use within the framework.
*
* @author Mark Angrish
*/
@@ -57,9 +57,7 @@ public class SessionFactoryUtils {
private static final Logger logger = LoggerFactory.getLogger(SessionFactoryUtils.class);
public static void closeSession(Session session) {
}
public static void closeSession(Session session) {}
public static Session getSession(SessionFactory sessionFactory) throws IllegalStateException {
@@ -67,11 +65,11 @@ public class SessionFactoryUtils {
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
if (sessionHolder != null) {
if (!sessionHolder.isSynchronizedWithTransaction() &&
TransactionSynchronizationManager.isSynchronizationActive()) {
if (!sessionHolder.isSynchronizedWithTransaction()
&& TransactionSynchronizationManager.isSynchronizationActive()) {
sessionHolder.setSynchronizedWithTransaction(true);
TransactionSynchronizationManager.registerSynchronization(
new SessionSynchronization(sessionHolder, sessionFactory, false));
TransactionSynchronizationManager
.registerSynchronization(new SessionSynchronization(sessionHolder, sessionFactory, false));
}
return sessionHolder.getSession();
}
@@ -88,22 +86,20 @@ public class SessionFactoryUtils {
sessionHolder = new SessionHolder(session);
sessionHolder.setSynchronizedWithTransaction(true);
TransactionSynchronizationManager.registerSynchronization(
new SessionSynchronization(sessionHolder, sessionFactory, true));
TransactionSynchronizationManager
.registerSynchronization(new SessionSynchronization(sessionHolder, sessionFactory, true));
TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
return session;
}
/**
* Convert the given runtime exception to an appropriate exception from the
* {@code org.springframework.dao} hierarchy.
* Return null if no translation is appropriate: any other exception may
* have resulted from user code, and should not be translated.
* Convert the given runtime exception to an appropriate exception from the {@code org.springframework.dao} hierarchy.
* Return null if no translation is appropriate: any other exception may have resulted from user code, and should not
* be translated.
*
* @param ex runtime exception that occurred
* @return the corresponding DataAccessException instance,
* or {@code null} if the exception should not be translated
* @return the corresponding DataAccessException instance, or {@code null} if the exception should not be translated
*/
public static DataAccessException convertOgmAccessException(RuntimeException ex) {
@@ -160,9 +156,11 @@ public class SessionFactoryUtils {
if (dae != null) {
try {
final Constructor<? extends DataAccessException> constructor = dae.getDeclaredConstructor(String.class, Throwable.class);
final Constructor<? extends DataAccessException> constructor = dae.getDeclaredConstructor(String.class,
Throwable.class);
return constructor.newInstance(ex.getMessage(), ex);
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException
| InvocationTargetException e) {
return null;
}
}
@@ -175,15 +173,12 @@ public class SessionFactoryUtils {
return null;
}
private static class SessionSynchronization
extends ResourceHolderSynchronization<SessionHolder, SessionFactory>
private static class SessionSynchronization extends ResourceHolderSynchronization<SessionHolder, SessionFactory>
implements Ordered {
private final boolean newSession;
SessionSynchronization(
SessionHolder sessionHolder, SessionFactory sessionFactory, boolean newSession) {
SessionSynchronization(SessionHolder sessionHolder, SessionFactory sessionFactory, boolean newSession) {
super(sessionHolder, sessionFactory);
this.newSession = newSession;
}
@@ -194,8 +189,7 @@ public class SessionFactoryUtils {
}
@Override
public void flushResource(SessionHolder resourceHolder) {
}
public void flushResource(SessionHolder resourceHolder) {}
@Override
protected boolean shouldUnbindAtCompletion() {
@@ -204,7 +198,7 @@ public class SessionFactoryUtils {
@Override
protected boolean shouldReleaseAfterCompletion(SessionHolder resourceHolder) {
// return !resourceHolder.getSession().isClosed();
// return !resourceHolder.getSession().isClosed();
return false;
}
}

View File

@@ -18,11 +18,10 @@ import org.springframework.transaction.support.ResourceHolderSupport;
import org.springframework.util.Assert;
/**
* Holder wrapping a Neo4j OGM Session.
* Neo4jTransactionManager binds instances of this class to the thread,
* for a given SessionFactory.
*
* <p>Note: This is an SPI class, not intended to be used by applications.
* Holder wrapping a Neo4j OGM Session. Neo4jTransactionManager binds instances of this class to the thread, for a given
* SessionFactory.
* <p>
* Note: This is an SPI class, not intended to be used by applications.
*
* @author Mark Angrish
* @see Neo4jTransactionManager
@@ -39,7 +38,6 @@ public class SessionHolder extends ResourceHolderSupport {
this.session = session;
}
public Session getSession() {
return this.session;
}
@@ -52,7 +50,6 @@ public class SessionHolder extends ResourceHolderSupport {
return this.transactionActive;
}
@Override
public void clear() {
super.clear();

View File

@@ -30,12 +30,11 @@ import org.slf4j.LoggerFactory;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* Delegate for creating a shareable Neo4j OGM {@link Session}
* reference for a given {@link SessionFactory}.
* <p>A shared Session will behave just like a Session fetched from
* an application SessionFactory.
* It will delegate all calls to the current transactional Session, if any;
* otherwise it will fall back to a newly created Session per operation.
* Delegate for creating a shareable Neo4j OGM {@link Session} reference for a given {@link SessionFactory}.
* <p>
* A shared Session will behave just like a Session fetched from an application SessionFactory. It will delegate all
* calls to the current transactional Session, if any; otherwise it will fall back to a newly created Session per
* operation.
*
* @author Mark Angrish
* @see Neo4jTransactionManager
@@ -54,22 +53,18 @@ public class SharedSessionCreator {
/**
* Create a transactional Session proxy for the given SessionFactory.
*
* @param sessionFactory SessionFactory to obtain Sessions from as needed
* {@code createSession} call (may be {@code null})
* Session. Allows the addition or specification of proprietary interfaces.
* @param sessionFactory SessionFactory to obtain Sessions from as needed {@code createSession} call (may be
* {@code null}) Session. Allows the addition or specification of proprietary interfaces.
* @return a shareable transactional Session proxy
*/
public static Session createSharedSession(SessionFactory sessionFactory) {
return (Session) Proxy.newProxyInstance(
SharedSessionCreator.class.getClassLoader(),
new Class<?>[]{Session.class}, new SharedSessionInvocationHandler(sessionFactory));
return (Session) Proxy.newProxyInstance(SharedSessionCreator.class.getClassLoader(),
new Class<?>[] { Session.class }, new SharedSessionInvocationHandler(sessionFactory));
}
/**
* Invocation handler that delegates all calls to the current
* transactional Session, if any; else, it will fall back
* Invocation handler that delegates all calls to the current transactional Session, if any; else, it will fall back
* to a newly created Session per operation.
*/
private static class SharedSessionInvocationHandler implements InvocationHandler {
@@ -84,7 +79,6 @@ public class SharedSessionCreator {
this.proxyClassLoader = this.targetFactory.getClass().getClassLoader();
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on Session interface coming in...
@@ -100,8 +94,7 @@ public class SharedSessionCreator {
return "Shared Session proxy for target factory [" + targetFactory + "]";
} else if (method.getName().equals("beginTransaction")) {
throw new IllegalStateException(
"Not allowed to create transaction on shared Session - " +
"use Spring transactions instead");
"Not allowed to create transaction on shared Session - " + "use Spring transactions instead");
}
// Determine current Session: either the transactional one
@@ -109,11 +102,11 @@ public class SharedSessionCreator {
Session target = SessionFactoryUtils.getSession(this.targetFactory);
if (transactionRequiringMethods.contains(method.getName())) {
if (target == null || (!TransactionSynchronizationManager.isActualTransactionActive()
&& target.getTransaction() != null
&& EnumSet.of(CLOSED, COMMITTED, ROLLEDBACK).contains(target.getTransaction().status()))) {
throw new IllegalStateException("No Session with actual transaction available " +
"for current thread - cannot reliably process '" + method.getName() + "' call");
if (target == null
|| (!TransactionSynchronizationManager.isActualTransactionActive() && target.getTransaction() != null
&& EnumSet.of(CLOSED, COMMITTED, ROLLEDBACK).contains(target.getTransaction().status()))) {
throw new IllegalStateException("No Session with actual transaction available "
+ "for current thread - cannot reliably process '" + method.getName() + "' call");
}
}

View File

@@ -13,13 +13,13 @@
package org.springframework.data.neo4j.util;
import org.neo4j.ogm.exception.core.NotFoundException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.neo4j.ogm.exception.core.NotFoundException;
/**
* Utility methods for dealing with {@link Iterable}s.
*
@@ -27,229 +27,228 @@ import java.util.List;
*/
public final class IterableUtils {
/**
* Count items in an iterable.
*
* @param iterable to count items in.
* @return number of items in the iterable.
*/
public static long count(Iterable iterable) {
if (iterable instanceof Collection) {
return ((Collection) iterable).size();
}
/**
* Count items in an iterable.
*
* @param iterable to count items in.
* @return number of items in the iterable.
*/
public static long count(Iterable iterable) {
if (iterable instanceof Collection) {
return ((Collection) iterable).size();
}
int count = 0;
for (Object o : iterable) {
count++;
}
int count = 0;
for (Object o : iterable) {
count++;
}
return count;
}
return count;
}
/**
* Check whether an iterable contains the given object.
*
* @param iterable to check in.
* @param object to look for.
* @param <T> type of the objects stored in the iterable.
* @return true iff the object is contained in the iterable.
*/
public static <T> boolean contains(Iterable<T> iterable, T object) {
if (iterable instanceof Collection) {
return ((Collection) iterable).contains(object);
}
/**
* Check whether an iterable contains the given object.
*
* @param iterable to check in.
* @param object to look for.
* @param <T> type of the objects stored in the iterable.
* @return true iff the object is contained in the iterable.
*/
public static <T> boolean contains(Iterable<T> iterable, T object) {
if (iterable instanceof Collection) {
return ((Collection) iterable).contains(object);
}
for (T t : iterable) {
if (t.equals(object)) {
return true;
}
}
for (T t : iterable) {
if (t.equals(object)) {
return true;
}
}
return false;
}
return false;
}
/**
* Convert an iterable to a list.
*
* @param iterable to convert.
* @param <T> type of the items held.
* @return a list.
*/
public static <T> List<T> toList(Iterable<T> iterable) {
List<T> list = new ArrayList<>();
/**
* Convert an iterable to a list.
*
* @param iterable to convert.
* @param <T> type of the items held.
* @return a list.
*/
public static <T> List<T> toList(Iterable<T> iterable) {
List<T> list = new ArrayList<>();
if (iterable instanceof Collection) {
list.addAll((Collection<T>) iterable);
} else {
for (T next : iterable) {
list.add(next);
}
}
if (iterable instanceof Collection) {
list.addAll((Collection<T>) iterable);
} else {
for (T next : iterable) {
list.add(next);
}
}
return list;
}
return list;
}
/**
* Get a single element from iterator.
*
* @param iterator to find a single element.
* @param notFoundMessage exception message if there are no elements.
* @param <T> type of the element.
* @return the element iff there is exactly one.
* @throws NotFoundException in case there are no elements.
* @throws IllegalStateException in case the iterable contains more than 1 element.
*/
public static <T> T getSingle(Iterator<T> iterator, String notFoundMessage) {
T result = getSingleOrNull(iterator);
/**
* Get a single element from iterator.
*
* @param iterator to find a single element.
* @param notFoundMessage exception message if there are no elements.
* @param <T> type of the element.
* @return the element iff there is exactly one.
* @throws NotFoundException in case there are no elements.
* @throws IllegalStateException in case the iterable contains more than 1 element.
*/
public static <T> T getSingle(Iterator<T> iterator, String notFoundMessage) {
T result = getSingleOrNull(iterator);
if (result == null) {
throw new NotFoundException(notFoundMessage);
}
if (result == null) {
throw new NotFoundException(notFoundMessage);
}
return result;
}
return result;
}
/**
* Get a single element from iterable.
*
* @param iterable to find a single element.
* @param notFoundMessage exception message if there are no elements.
* @param <T> type of the element.
* @return the element iff there is exactly one.
* @throws NotFoundException in case there are no elements.
* @throws IllegalStateException in case the iterable contains more than 1 element.
*/
public static <T> T getSingle(Iterable<T> iterable, String notFoundMessage) {
return getSingle(iterable.iterator(), notFoundMessage);
}
/**
* Get a single element from iterable.
*
* @param iterable to find a single element.
* @param notFoundMessage exception message if there are no elements.
* @param <T> type of the element.
* @return the element iff there is exactly one.
* @throws NotFoundException in case there are no elements.
* @throws IllegalStateException in case the iterable contains more than 1 element.
*/
public static <T> T getSingle(Iterable<T> iterable, String notFoundMessage) {
return getSingle(iterable.iterator(), notFoundMessage);
}
/**
* Get a single element from iterator.
*
* @param iterator to find a single element.
* @param <T> type of the element.
* @return the element iff there is exactly one.
* @throws NotFoundException in case there are no elements.
* @throws IllegalStateException in case the iterable contains more than 1 element.
*/
public static <T> T getSingle(Iterator<T> iterator) {
return getSingle(iterator, "Iterator is empty");
}
/**
* Get a single element from iterator.
*
* @param iterator to find a single element.
* @param <T> type of the element.
* @return the element iff there is exactly one.
* @throws NotFoundException in case there are no elements.
* @throws IllegalStateException in case the iterable contains more than 1 element.
*/
public static <T> T getSingle(Iterator<T> iterator) {
return getSingle(iterator, "Iterator is empty");
}
/**
* Get a single element from iterable.
*
* @param iterable to find a single element.
* @param <T> type of the element.
* @return the element iff there is exactly one.
* @throws NotFoundException in case there are no elements.
* @throws IllegalStateException in case the iterable contains more than 1 element.
*/
public static <T> T getSingle(Iterable<T> iterable) {
return getSingle(iterable.iterator(), "Iterable is empty");
}
/**
* Get a single element from iterable.
*
* @param iterable to find a single element.
* @param <T> type of the element.
* @return the element iff there is exactly one.
* @throws NotFoundException in case there are no elements.
* @throws IllegalStateException in case the iterable contains more than 1 element.
*/
public static <T> T getSingle(Iterable<T> iterable) {
return getSingle(iterable.iterator(), "Iterable is empty");
}
/**
* Get a single element from iterator.
*
* @param iterator to find a single element.
* @param <T> type of the element.
* @return the element iff there is exactly one, null iff there is 0.
* @throws IllegalStateException in case the iterable contains more than 1 element.
*/
public static <T> T getSingleOrNull(Iterator<T> iterator) {
T result = null;
/**
* Get a single element from iterator.
*
* @param iterator to find a single element.
* @param <T> type of the element.
* @return the element iff there is exactly one, null iff there is 0.
* @throws IllegalStateException in case the iterable contains more than 1 element.
*/
public static <T> T getSingleOrNull(Iterator<T> iterator) {
T result = null;
if (iterator.hasNext()) {
result = iterator.next();
}
if (iterator.hasNext()) {
result = iterator.next();
}
if (iterator.hasNext()) {
throw new IllegalStateException("Iterable has more than one element, which is unexpected");
}
if (iterator.hasNext()) {
throw new IllegalStateException("Iterable has more than one element, which is unexpected");
}
return result;
}
return result;
}
/**
* Get a single element from iterable.
*
* @param iterable to find a single element.
* @param <T> type of the element.
* @return the element iff there is exactly one, null iff there is 0.
* @throws IllegalStateException in case the iterable contains more than 1 element.
*/
public static <T> T getSingleOrNull(Iterable<T> iterable) {
return getSingleOrNull(iterable.iterator());
}
/**
* Get a single element from iterable.
*
* @param iterable to find a single element.
* @param <T> type of the element.
* @return the element iff there is exactly one, null iff there is 0.
* @throws IllegalStateException in case the iterable contains more than 1 element.
*/
public static <T> T getSingleOrNull(Iterable<T> iterable) {
return getSingleOrNull(iterable.iterator());
}
/**
* Get the first element from iterator.
*
* @param iterator to find the first element.
* @param notFoundMessage exception message if there are no elements.
* @param <T> type of the element.
* @return the element iff there is one or more.
* @throws NotFoundException in case there are no elements.
*/
public static <T> T getFirst(Iterator<T> iterator, String notFoundMessage) {
T result = null;
/**
* Get the first element from iterator.
*
* @param iterator to find the first element.
* @param notFoundMessage exception message if there are no elements.
* @param <T> type of the element.
* @return the element iff there is one or more.
* @throws NotFoundException in case there are no elements.
*/
public static <T> T getFirst(Iterator<T> iterator, String notFoundMessage) {
T result = null;
if (iterator.hasNext()) {
result = iterator.next();
}
if (iterator.hasNext()) {
result = iterator.next();
}
if (result == null) {
throw new NotFoundException(notFoundMessage);
}
if (result == null) {
throw new NotFoundException(notFoundMessage);
}
return result;
}
return result;
}
/**
* Get the first element from iterable.
*
* @param iterable to find the first element.
* @param notFoundMessage exception message if there are no elements.
* @param <T> type of the element.
* @return the element iff there is one or more.
* @throws NotFoundException in case there are no elements.
*/
public static <T> T getFirst(Iterable<T> iterable, String notFoundMessage) {
return getFirst(iterable.iterator(), notFoundMessage);
}
/**
* Get the first element from iterable.
*
* @param iterable to find the first element.
* @param notFoundMessage exception message if there are no elements.
* @param <T> type of the element.
* @return the element iff there is one or more.
* @throws NotFoundException in case there are no elements.
*/
public static <T> T getFirst(Iterable<T> iterable, String notFoundMessage) {
return getFirst(iterable.iterator(), notFoundMessage);
}
/**
* Get the first element from iterator.
*
* @param iterator to find the first element.
* @param <T> type of the element.
* @return the element iff there is one or more, null if there is none.
*/
public static <T> T getFirstOrNull(Iterator<T> iterator) {
T result = null;
/**
* Get the first element from iterator.
*
* @param iterator to find the first element.
* @param <T> type of the element.
* @return the element iff there is one or more, null if there is none.
*/
public static <T> T getFirstOrNull(Iterator<T> iterator) {
T result = null;
if (iterator.hasNext()) {
result = iterator.next();
}
if (iterator.hasNext()) {
result = iterator.next();
}
return result;
}
return result;
}
/**
* Get the first element from iterable.
*
* @param iterable to find the first element.
* @param <T> type of the element.
* @return the element iff there is one or more, null if there is none.
*/
public static <T> T getFirstOrNull(Iterable<T> iterable) {
return getFirstOrNull(iterable.iterator());
}
/**
* Get the first element from iterable.
*
* @param iterable to find the first element.
* @param <T> type of the element.
* @return the element iff there is one or more, null if there is none.
*/
public static <T> T getFirstOrNull(Iterable<T> iterable) {
return getFirstOrNull(iterable.iterator());
}
/**
* private constructor to prevent instantiation.
*/
private IterableUtils() {
}
/**
* private constructor to prevent instantiation.
*/
private IterableUtils() {}
}

View File

@@ -26,15 +26,14 @@ import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.context.request.async.DeferredResultProcessingInterceptor;
/**
* An interceptor with asynchronous web requests used in OpenSessionInViewFilter and
* OpenSessionInViewInterceptor.
* Ensures the following:
* 1) The session is bound/unbound when "callable processing" is started
* 2) The session is closed if an async request times out
* An interceptor with asynchronous web requests used in OpenSessionInViewFilter and OpenSessionInViewInterceptor.
* Ensures the following: 1) The session is bound/unbound when "callable processing" is started 2) The session is closed
* if an async request times out
*
* @author Mark Angrish
*/
class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter implements DeferredResultProcessingInterceptor {
class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter
implements DeferredResultProcessingInterceptor {
private static final Logger logger = LoggerFactory.getLogger(AsyncRequestInterceptor.class);
@@ -49,7 +48,6 @@ class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter imple
this.sessionHolder = sessionHolder;
}
@Override
public <T> void preProcess(NativeWebRequest request, Callable<T> task) {
bindSession();
@@ -68,7 +66,7 @@ class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter imple
@Override
public <T> Object handleTimeout(NativeWebRequest request, Callable<T> task) {
this.timeoutInProgress = true;
return RESULT_NONE; // give other interceptors a chance to handle the timeout
return RESULT_NONE; // give other interceptors a chance to handle the timeout
}
@Override
@@ -80,13 +78,12 @@ class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter imple
if (this.timeoutInProgress) {
logger.debug("Closing Neo4j OGM Session after async request timeout");
// close session.
// SessionFactoryUtils.closeSession(session);
// SessionFactoryUtils.closeSession(session);
}
}
@Override
public <T> void beforeConcurrentHandling(NativeWebRequest request, DeferredResult<T> deferredResult) {
}
public <T> void beforeConcurrentHandling(NativeWebRequest request, DeferredResult<T> deferredResult) {}
@Override
public <T> void preProcess(NativeWebRequest request, DeferredResult<T> deferredResult) {
@@ -101,11 +98,12 @@ class AsyncRequestInterceptor extends CallableProcessingInterceptorAdapter imple
@Override
public <T> boolean handleTimeout(NativeWebRequest request, DeferredResult<T> deferredResult) {
this.timeoutInProgress = true;
return true; // give other interceptors a chance to handle the timeout
return true; // give other interceptors a chance to handle the timeout
}
@Override
public <T> void afterCompletion(NativeWebRequest nativeWebRequest, DeferredResult<T> deferredResult) throws Exception {
public <T> void afterCompletion(NativeWebRequest nativeWebRequest, DeferredResult<T> deferredResult)
throws Exception {
// Do nothing.
}
}

View File

@@ -13,16 +13,16 @@
package org.springframework.data.neo4j.web.support;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.data.neo4j.transaction.Neo4jTransactionManager;
import org.springframework.data.neo4j.transaction.SessionFactoryUtils;
import org.springframework.data.neo4j.transaction.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.StringUtils;
@@ -33,16 +33,15 @@ import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.filter.OncePerRequestFilter;
/**
* Servlet Filter that binds a Neo4j OGM Session to the thread for the
* entire processing of the request. Intended for the "Open Session in
* View" pattern, i.e. to allow for lazy loading in web views despite the
* original transactions already being completed.
* <p>This filter makes OGM Sessions available via the current thread,
* which will be autodetected by transaction managers. At the moment this service is
* only suitable for transactions via {@link Neo4jTransactionManager}.
* <p>Looks up the SessionFactory in Spring's root web application context.
* Supports an "sessionFactoryBeanName" filter init-param in {@code web.xml};
* the default bean name is "sessionFactory".
* Servlet Filter that binds a Neo4j OGM Session to the thread for the entire processing of the request. Intended for
* the "Open Session in View" pattern, i.e. to allow for lazy loading in web views despite the original transactions
* already being completed.
* <p>
* This filter makes OGM Sessions available via the current thread, which will be autodetected by transaction managers.
* At the moment this service is only suitable for transactions via {@link Neo4jTransactionManager}.
* <p>
* Looks up the SessionFactory in Spring's root web application context. Supports an "sessionFactoryBeanName" filter
* init-param in {@code web.xml}; the default bean name is "sessionFactory".
*
* @author Mark Angrish
* @see OpenSessionInViewInterceptor
@@ -63,9 +62,9 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
private volatile SessionFactory sessionFactory;
/**
* Set the bean name of the SessionFactory to fetch from Spring's
* root application context.
* <p>Default is "sessionFactory".
* Set the bean name of the SessionFactory to fetch from Spring's root application context.
* <p>
* Default is "sessionFactory".
*
* @see #DEFAULT_SESSION_FACTORY_BEAN_NAME
*/
@@ -74,38 +73,31 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
}
/**
* Return the bean name of the SessionFactory to fetch from Spring's
* root application context.
* Return the bean name of the SessionFactory to fetch from Spring's root application context.
*/
protected String getSessionFactoryBeanName() {
return this.sessionFactoryBeanName;
}
/**
* Returns "false" so that the filter may re-bind the opened {@code Session}
* to each asynchronously dispatched thread and postpone closing it until the very
* last asynchronous dispatch.
* Returns "false" so that the filter may re-bind the opened {@code Session} to each asynchronously dispatched thread
* and postpone closing it until the very last asynchronous dispatch.
*/
@Override
protected boolean shouldNotFilterAsyncDispatch() {
return false;
}
/**
* Returns "false" so that the filter may provide an {@code Session}
* to each error dispatches.
* Returns "false" so that the filter may provide an {@code Session} to each error dispatches.
*/
@Override
protected boolean shouldNotFilterErrorDispatch() {
return false;
}
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
SessionFactory sessionFactory = lookupSessionFactory(request);
@@ -139,17 +131,17 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
if (!isAsyncStarted(request)) {
logger.debug("Closed Neo4J OGM Session in OpenSessionInViewFilter");
// close session.
// SessionFactoryUtils.closeSession(session);
// SessionFactoryUtils.closeSession(session);
}
}
}
}
/**
* Look up the SessionFactory that this filter should use,
* taking the current HTTP request as argument.
* <p>The default implementation delegates to the {@code lookupSessionFactory}
* without arguments, caching the SessionFactory reference once obtained.
* Look up the SessionFactory that this filter should use, taking the current HTTP request as argument.
* <p>
* The default implementation delegates to the {@code lookupSessionFactory} without arguments, caching the
* SessionFactory reference once obtained.
*
* @return the SessionFactory to use
* @see #lookupSessionFactory()
@@ -163,8 +155,8 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
/**
* Look up the SessionFactory that this filter should use.
* <p>The default implementation looks for a bean with the specified name
* in Spring's root application context.
* <p>
* The default implementation looks for a bean with the specified name in Spring's root application context.
*
* @return the SessionFactory to use
* @see #getSessionFactoryBeanName
@@ -182,10 +174,10 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
}
}
/**
* Create a Neo4j OGM Session to be bound to a request.
* <p>Can be overridden in subclasses.
* <p>
* Can be overridden in subclasses.
*
* @param sessionFactory the SessionFactory to use
* @see SessionFactory#openSession

View File

@@ -13,7 +13,6 @@
package org.springframework.data.neo4j.web.support;
import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
import org.slf4j.Logger;
@@ -32,15 +31,15 @@ import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
/**
* Spring web request interceptor that binds a Neo4j OGM Session to the
* thread for the entire processing of the request. Intended for the "Open
* Session in View" pattern, i.e. to allow for lazy loading in
* web views despite the original transactions already being completed.
* <p>This interceptor makes Neo4j OGM Sessions available via the current thread,
* which will be autodetected by transaction managers. It is suitable for service
* layer transactions via {@link Neo4jTransactionManager}.
* <p>In contrast to {@link OpenSessionInViewFilter}, this interceptor is set
* up in a Spring application context and can thus take advantage of bean wiring.
* Spring web request interceptor that binds a Neo4j OGM Session to the thread for the entire processing of the request.
* Intended for the "Open Session in View" pattern, i.e. to allow for lazy loading in web views despite the original
* transactions already being completed.
* <p>
* This interceptor makes Neo4j OGM Sessions available via the current thread, which will be autodetected by transaction
* managers. It is suitable for service layer transactions via {@link Neo4jTransactionManager}.
* <p>
* In contrast to {@link OpenSessionInViewFilter}, this interceptor is set up in a Spring application context and can
* thus take advantage of bean wiring.
*
* @author Mark Angrish
* @see OpenSessionInViewFilter
@@ -55,8 +54,7 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
protected final Logger logger = LoggerFactory.getLogger(getClass());
/**
* Suffix that gets appended to the SessionFactory toString
* representation for the "participate in existing session
* Suffix that gets appended to the SessionFactory toString representation for the "participate in existing session
* handling" request attribute.
*
* @see #getParticipateAttributeName
@@ -66,8 +64,7 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
private SessionFactory sessionFactory;
/**
* Set the Neo4j OGM SessionFactory that should be used to create
* Sessions.
* Set the Neo4j OGM SessionFactory that should be used to create Sessions.
*
* @see SessionFactory#openSession
*/
@@ -76,8 +73,7 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
}
/**
* Return the Neo4j OGM SessionFactory that should be used to create
* Sessions.
* Return the Neo4j OGM SessionFactory that should be used to create Sessions.
*/
public SessionFactory getSessionFactory() {
return this.sessionFactory;
@@ -93,7 +89,6 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
}
}
@Override
public void preHandle(WebRequest request) throws DataAccessException {
String participateAttributeName = getParticipateAttributeName();
@@ -123,8 +118,7 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
}
@Override
public void postHandle(WebRequest request, ModelMap model) {
}
public void postHandle(WebRequest request, ModelMap model) {}
@Override
public void afterCompletion(WebRequest request, Exception ex) throws DataAccessException {
@@ -132,7 +126,7 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
TransactionSynchronizationManager.unbindResource(getSessionFactory());
logger.debug("Closed Neo4j OGM Session in OpenSessionInViewInterceptor");
// close session.
// SessionFactoryUtils.closeSession(session);
// SessionFactoryUtils.closeSession(session);
}
}
@@ -159,9 +153,8 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
}
/**
* Return the name of the request attribute that identifies that a request is
* already filtered. Default implementation takes the toString representation
* of the SessionFactory instance and appends ".FILTERED".
* Return the name of the request attribute that identifies that a request is already filtered. Default implementation
* takes the toString representation of the SessionFactory instance and appends ".FILTERED".
*
* @see #PARTICIPATE_SUFFIX
*/
@@ -169,7 +162,6 @@ public class OpenSessionInViewInterceptor implements BeanFactoryAware, AsyncWebR
return getSessionFactory().toString() + PARTICIPATE_SUFFIX;
}
private boolean applyCallableInterceptor(WebAsyncManager asyncManager, String key) {
if (asyncManager.getCallableInterceptor(key) == null) {
return false;

View File

@@ -48,20 +48,19 @@ public class JavaConfigurationAuditingTests extends MultiDriverTestClass {
@EnableNeo4jRepositories(basePackageClasses = UserRepository.class)
static class Neo4jConfiguration {
@Bean
public SessionFactory sessionFactory() {
return new SessionFactory(getBaseConfiguration().build(), User.class.getPackage().getName());
return new SessionFactory(getBaseConfiguration().build(), User.class.getPackage().getName());
}
@Bean
public Neo4jTransactionManager transactionManager() {
return new Neo4jTransactionManager();
return new Neo4jTransactionManager();
}
@Bean
public AuditorAware<String> auditorAware() {
return new AuditorAware<String>() {
return new AuditorAware<String>() {
@Override
public Optional<String> getCurrentAuditor() {
@@ -71,8 +70,7 @@ public class JavaConfigurationAuditingTests extends MultiDriverTestClass {
}
}
@Autowired
private UserRepository userRepository;
@Autowired private UserRepository userRepository;
@Test
public void whenSaveEntity_thenSetCreatedAndCreatedBy() throws Exception {

View File

@@ -13,14 +13,14 @@
package org.springframework.data.neo4j.auditing.domain;
import java.time.LocalDateTime;
import org.neo4j.ogm.annotation.NodeEntity;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import java.time.LocalDateTime;
/**
* @author Frantisek Hartman
*/
@@ -31,20 +31,15 @@ public class User {
String name;
@CreatedDate
LocalDateTime created;
@CreatedDate LocalDateTime created;
@CreatedBy
String createdBy;
@CreatedBy String createdBy;
@LastModifiedDate
LocalDateTime modified;
@LastModifiedDate LocalDateTime modified;
@LastModifiedBy
String modifiedBy;
@LastModifiedBy String modifiedBy;
public User() {
}
public User() {}
public User(String name) {
this.name = name;

View File

@@ -19,5 +19,4 @@ import org.springframework.data.neo4j.repository.Neo4jRepository;
/**
* @author Frantisek Hartman
*/
public interface UserRepository extends Neo4jRepository<User, Long> {
}
public interface UserRepository extends Neo4jRepository<User, Long> {}

View File

@@ -13,6 +13,8 @@
package org.springframework.data.neo4j.bookmark;
import static org.assertj.core.api.Assertions.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -24,8 +26,6 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Frantisek Hartman
*/
@@ -33,11 +33,9 @@ import static org.assertj.core.api.Assertions.assertThat;
@ContextConfiguration(classes = BookmarkManagementTest.BookmarkManagementConfiguration.class)
public class BookmarkManagementTest {
@Autowired
private UseBookmarkOnMethodBean useBookmarkOnMethodBean;
@Autowired private UseBookmarkOnMethodBean useBookmarkOnMethodBean;
@Autowired
private UseBookmarkOnClassBean useBookmarkOnClassBean;
@Autowired private UseBookmarkOnClassBean useBookmarkOnClassBean;
@Test
public void givenUseBookmarkOnMethod_whenRun_thenShouldUseBookmarkIsSet() throws Exception {
@@ -50,8 +48,7 @@ public class BookmarkManagementTest {
@Test
public void givenUseBookmarkOnMethod_whenRun_thenRemoveBookmarkInfoAfterRun() throws Exception {
useBookmarkOnMethodBean.runWithBookmark(() -> {
});
useBookmarkOnMethodBean.runWithBookmark(() -> {});
BookmarkInfo bookmarkInfo = BookmarkSupport.currentBookmarkInfo();
assertThat(bookmarkInfo).isNull();
@@ -84,8 +81,7 @@ public class BookmarkManagementTest {
@Test
public void givenUseBookmarkOnClass_whenRun_thenRemoveBookmarkInfoAfterRun() throws Exception {
useBookmarkOnClassBean.runWithBookmark(() -> {
});
useBookmarkOnClassBean.runWithBookmark(() -> {});
BookmarkInfo bookmarkInfo = BookmarkSupport.currentBookmarkInfo();
assertThat(bookmarkInfo).isNull();
@@ -134,5 +130,4 @@ public class BookmarkManagementTest {
}
}

View File

@@ -12,7 +12,6 @@
*/
package org.springframework.data.neo4j.domain.sample;
import java.util.UUID;
import org.neo4j.ogm.annotation.GraphId;
@@ -28,8 +27,7 @@ public class Role {
private static final String PREFIX = "ROLE_";
@GraphId
private Long id;
@GraphId private Long id;
private UUID uuid;
private String name;

View File

@@ -23,8 +23,7 @@ import org.springframework.util.Assert;
@NodeEntity
public class SampleEntity {
@GraphId
protected Long id;
@GraphId protected Long id;
private String first;
private String second;

View File

@@ -10,7 +10,6 @@ import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
import org.neo4j.ogm.annotation.typeconversion.DateString;
/**
* Domain class representing a person emphasizing the use of {@code AbstractEntity}. No declaration of an id is
* required. The id is typed by the parameterizable superclass.
@@ -18,8 +17,7 @@ import org.neo4j.ogm.annotation.typeconversion.DateString;
@NodeEntity
public class User {
@GraphId
private Long id;
@GraphId private Long id;
private String firstname;
@@ -33,11 +31,9 @@ public class User {
private String emailAddress;
@Relationship
private Set<User> colleagues;
@Relationship private Set<User> colleagues;
@Relationship
private Set<Role> roles;
@Relationship private Set<Role> roles;
private User manager;
@@ -47,8 +43,7 @@ public class User {
private Set<String> attributes;
@DateString
private Date dateOfBirth;
@DateString private Date dateOfBirth;
/**
* Creates a new empty instance of {@code User}.

View File

@@ -12,8 +12,7 @@ import org.springframework.stereotype.Component;
@Component
public class EventPublisher extends EventListenerAdapter {
@Autowired
private ApplicationEventPublisher publisher;
@Autowired private ApplicationEventPublisher publisher;
@Override
public void onPreSave(Event event) {

View File

@@ -1,7 +1,6 @@
package org.springframework.data.neo4j.events;
import org.springframework.context.event.EventListener;
import org.springframework.core.ResolvableType;
import org.springframework.stereotype.Component;
/**
@@ -21,7 +20,7 @@ public class Neo4jModificationEventListener {
@EventListener
public void onPreSaveEvent(PreSaveEvent event) {
preSaveEvent= event;
preSaveEvent = event;
preSaveEventCount++;
}

View File

@@ -7,7 +7,7 @@ import org.neo4j.ogm.session.event.Event;
*/
public class PostDeleteEvent extends ModificationEvent {
public PostDeleteEvent( Event event) {
public PostDeleteEvent(Event event) {
super(event);
}
}

View File

@@ -7,7 +7,7 @@ import org.neo4j.ogm.session.event.Event;
*/
public class PreDeleteEvent extends ModificationEvent {
public PreDeleteEvent( Event event) {
public PreDeleteEvent(Event event) {
super(event);
}
}

View File

@@ -27,8 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
@Service
public class FriendService {
@Autowired
Session session;
@Autowired Session session;
@Transactional
public void createPersonAndFriends() {

View File

@@ -16,10 +16,8 @@ package org.springframework.data.neo4j.examples.friends;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.ogm.cypher.ComparisonOperator;
import org.neo4j.ogm.cypher.Filter;
import org.neo4j.ogm.session.Session;
@@ -44,16 +42,14 @@ import org.springframework.transaction.annotation.Transactional;
* @author Luanne Misquitta
* @author Mark Angrish
*/
@ContextConfiguration(classes = {FriendTests.FriendContext.class})
@ContextConfiguration(classes = { FriendTests.FriendContext.class })
@RunWith(SpringJUnit4ClassRunner.class)
public class FriendTests extends MultiDriverTestClass {
@Autowired Session session;
@Autowired FriendshipRepository friendshipRepository;
@Autowired FriendService friendService;
@Before
public void cleanUpDatabase() {
getGraphDatabaseService().execute("MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE r, n");
@@ -68,7 +64,8 @@ public class FriendTests extends MultiDriverTestClass {
friendService.createPersonAndFriends();
session.clear();
Person john = session.loadAll(Person.class, new Filter("firstName", ComparisonOperator.EQUALS, "John")).iterator().next();
Person john = session.loadAll(Person.class, new Filter("firstName", ComparisonOperator.EQUALS, "John")).iterator()
.next();
assertNotNull(john);
assertEquals(2, john.getFriendships().size());
}
@@ -111,7 +108,8 @@ public class FriendTests extends MultiDriverTestClass {
@Bean
public SessionFactory sessionFactory() {
return new SessionFactory(getBaseConfiguration().build(), "org.springframework.data.neo4j.examples.friends.domain");
return new SessionFactory(getBaseConfiguration().build(),
"org.springframework.data.neo4j.examples.friends.domain");
}
}

View File

@@ -13,13 +13,13 @@
package org.springframework.data.neo4j.examples.friends.domain;
import java.util.HashSet;
import java.util.Set;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
import java.util.HashSet;
import java.util.Set;
/**
* @author Luanne Misquitta
*/
@@ -30,8 +30,7 @@ public class Person {
private String firstName;
private String lastName;
@Relationship(type = "IS_FRIEND")
private Set<Friendship> friendships = new HashSet<>();
@Relationship(type = "IS_FRIEND") private Set<Friendship> friendships = new HashSet<>();
public Person() {}

View File

@@ -49,18 +49,16 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
/**
* @author Vince Bickers
* @author Mark Paluch
*/
@ContextConfiguration(classes = {GalaxyServiceTests.GalaxyContext.class})
@ContextConfiguration(classes = { GalaxyServiceTests.GalaxyContext.class })
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
public class GalaxyServiceTests extends MultiDriverTestClass {
@Autowired
private GalaxyService galaxyService;
@Autowired private GalaxyService galaxyService;
@Before
public void setUp() {
@@ -108,7 +106,6 @@ public class GalaxyServiceTests extends MultiDriverTestClass {
}
}
@Test
public void shouldFindWorldsByName() {
galaxyService.makeSomeWorlds();
@@ -150,9 +147,7 @@ public class GalaxyServiceTests extends MultiDriverTestClass {
galaxyService.makeSomeWorlds();
for (World worldWithOneMoon : galaxyService.findAllByNumberOfMoons(1)) {
assertThat(
worldWithOneMoon.getName(),
is(anyOf(containsString("Earth"), containsString("Midgard"))));
assertThat(worldWithOneMoon.getName(), is(anyOf(containsString("Earth"), containsString("Midgard"))));
}
}
@@ -221,11 +216,11 @@ public class GalaxyServiceTests extends MultiDriverTestClass {
sum += world.getId();
}
// note: this doesn't work, because deleted node ids are not reclaimed
// long sum = (size * size - size) / 2; // 0-based node ids
// long sum = (size * size - size) / 2; // 0-based node ids
Pageable pageable = new PageRequest(0, 3);
for (; ; ) {
for (;;) {
Page<World> page = galaxyService.findAllWorlds(pageable);
for (World world : page) {
sum -= world.getId();
@@ -251,7 +246,7 @@ public class GalaxyServiceTests extends MultiDriverTestClass {
Pageable pageable = new PageRequest(0, 3, Sort.Direction.ASC, "name");
int i = 0;
for (; ; ) {
for (;;) {
Page<World> page = galaxyService.findAllWorlds(pageable);
for (World world : page) {
assertEquals(sortedNames[i], world.getName());
@@ -308,13 +303,13 @@ public class GalaxyServiceTests extends MultiDriverTestClass {
names.add(world.getName());
}
String[] sortedNames = names.toArray(new String[]{});
String[] sortedNames = names.toArray(new String[] {});
Arrays.sort(sortedNames);
return sortedNames;
}
@Configuration
@ComponentScan({"org.springframework.data.neo4j.examples.galaxy.service"})
@ComponentScan({ "org.springframework.data.neo4j.examples.galaxy.service" })
@EnableNeo4jRepositories("org.springframework.data.neo4j.examples.galaxy.repo")
@EnableTransactionManagement
static class GalaxyContext {
@@ -326,7 +321,8 @@ public class GalaxyServiceTests extends MultiDriverTestClass {
@Bean
public SessionFactory sessionFactory() {
return new SessionFactory(getBaseConfiguration().build(), "org.springframework.data.neo4j.examples.galaxy.domain");
return new SessionFactory(getBaseConfiguration().build(),
"org.springframework.data.neo4j.examples.galaxy.domain");
}
@Bean

View File

@@ -37,82 +37,81 @@ import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.support.TransactionTemplate;
@ContextConfiguration(classes = {WorldRepositoryTests.GalaxyContext.class})
@ContextConfiguration(classes = { WorldRepositoryTests.GalaxyContext.class })
@RunWith(SpringJUnit4ClassRunner.class)
public class WorldRepositoryTests extends MultiDriverTestClass {
@Autowired
WorldRepository worldRepository;
@Autowired WorldRepository worldRepository;
@Autowired
TransactionTemplate transactionTemplate;
@Autowired TransactionTemplate transactionTemplate;
boolean failed = false;
boolean failed = false;
/**
* see https://jira.spring.io/browse/DATAGRAPH-951
*
* @throws Exception
*/
@Test
public void multipleThreadsResultsGetMixedUp() throws Exception {
/**
* see https://jira.spring.io/browse/DATAGRAPH-951
*
* @throws Exception
*/
@Test
public void multipleThreadsResultsGetMixedUp() throws Exception {
World world1 = new World("world 1", 1);
worldRepository.save(world1, 0);
World world1 = new World("world 1", 1);
worldRepository.save(world1, 0);
World world2 = new World("world 2", 2);
worldRepository.save(world2, 0);
World world2 = new World("world 2", 2);
worldRepository.save(world2, 0);
int iterations = 10;
int iterations = 10;
ExecutorService service = Executors.newFixedThreadPool(2);
final CountDownLatch countDownLatch = new CountDownLatch(iterations * 2);
ExecutorService service = Executors.newFixedThreadPool(2);
final CountDownLatch countDownLatch = new CountDownLatch(iterations * 2);
for (int i = 0; i < iterations; i++) {
for (int i = 0; i < iterations; i++) {
service.execute(() -> {
World world = worldRepository.findByName("world 1");
service.execute(() -> {
World world = worldRepository.findByName("world 1");
if (!"world 1".equals(world.getName())) {
failed = true;
}
countDownLatch.countDown();
});
if (!"world 1".equals(world.getName())) {
failed = true;
}
countDownLatch.countDown();
});
service.execute(() -> {
service.execute(() -> {
World world = worldRepository.findByName("world 2");
World world = worldRepository.findByName("world 2");
if (!"world 2".equals(world.getName())) {
failed = true;
}
countDownLatch.countDown();
});
}
countDownLatch.await();
assertFalse(failed);
}
if (!"world 2".equals(world.getName())) {
failed = true;
}
countDownLatch.countDown();
});
}
countDownLatch.await();
assertFalse(failed);
}
@Configuration
@ComponentScan({"org.springframework.data.neo4j.examples.galaxy.service"})
@EnableNeo4jRepositories("org.springframework.data.neo4j.examples.galaxy.repo")
@EnableTransactionManagement
static class GalaxyContext {
@Configuration
@ComponentScan({ "org.springframework.data.neo4j.examples.galaxy.service" })
@EnableNeo4jRepositories("org.springframework.data.neo4j.examples.galaxy.repo")
@EnableTransactionManagement
static class GalaxyContext {
@Bean
public PlatformTransactionManager transactionManager() {
return new Neo4jTransactionManager(sessionFactory());
}
@Bean
public PlatformTransactionManager transactionManager() {
return new Neo4jTransactionManager(sessionFactory());
}
@Bean
public SessionFactory sessionFactory() {
return new SessionFactory(getBaseConfiguration().build(), "org.springframework.data.neo4j.examples.galaxy.domain");
}
@Bean
public SessionFactory sessionFactory() {
return new SessionFactory(getBaseConfiguration().build(),
"org.springframework.data.neo4j.examples.galaxy.domain");
}
@Bean
public TransactionTemplate transactionTemplate() {
return new TransactionTemplate(transactionManager());
}
@Bean
public TransactionTemplate transactionTemplate() {
return new TransactionTemplate(transactionManager());
}
}
}
}

View File

@@ -13,114 +13,117 @@
package org.springframework.data.neo4j.examples.galaxy.domain;
import org.neo4j.ogm.annotation.Relationship;
import java.util.HashSet;
import java.util.Set;
import org.neo4j.ogm.annotation.Relationship;
/**
* @author Vince Bickers
* @author Luanne Misquitta
*/
public class World {
private final static String REACHABLE_BY_ROCKET = "REACHABLE_BY_ROCKET";
private final static String REACHABLE_BY_ROCKET = "REACHABLE_BY_ROCKET";
private Long id;
private Long id;
private String name;
private String name;
private int moons;
private int moons;
private Float radius;
private Float radius;
private Long updated;
private Long updated;
public Long getUpdated() {
return updated;
}
public Long getUpdated() {
return updated;
}
public void setUpdated(long updated) {
this.updated = updated;
}
public void setUpdated(long updated) {
this.updated = updated;
}
@Relationship(type=REACHABLE_BY_ROCKET, direction = "UNDIRECTED")
private Set<World> reachableByRocket = new HashSet<>();
@Relationship(type = REACHABLE_BY_ROCKET,
direction = "UNDIRECTED") private Set<World> reachableByRocket = new HashSet<>();
public World(String name, int moons) {
this.name = name;
this.moons = moons;
}
public World(String name, int moons) {
this.name = name;
this.moons = moons;
}
public World() {
}
public World() {}
public Long getId() {
return id;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public int getMoons() {
return moons;
}
public int getMoons() {
return moons;
}
public void addRocketRouteTo(World otherWorld) {
reachableByRocket.add(otherWorld);
// symmetric relationship.
otherWorld.reachableByRocket.add(this); // bi-directional in domain.
}
public void addRocketRouteTo(World otherWorld) {
reachableByRocket.add(otherWorld);
// symmetric relationship.
otherWorld.reachableByRocket.add(this); // bi-directional in domain.
}
public Set<World> getReachableByRocket() {
return this.reachableByRocket;
}
public Set<World> getReachableByRocket() {
return this.reachableByRocket;
}
public void setReachableByRocket(Set<World> reachableByRocket) {
this.reachableByRocket.clear();
this.reachableByRocket = reachableByRocket;
}
public void setReachableByRocket(Set<World> reachableByRocket) {
this.reachableByRocket.clear();
this.reachableByRocket = reachableByRocket;
}
public boolean canBeReachedFrom(World otherWorld) {
for(World world : reachableByRocket) {
if(world.equals(otherWorld)) {
return true;
}
}
return false;
}
public boolean canBeReachedFrom(World otherWorld) {
for (World world : reachableByRocket) {
if (world.equals(otherWorld)) {
return true;
}
}
return false;
}
public Float getRadius() {
return radius;
}
public Float getRadius() {
return radius;
}
public void setRadius(Float radius) {
this.radius = radius;
}
public void setRadius(Float radius) {
this.radius = radius;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
World world = (World) o;
World world = (World) o;
if (moons != world.moons) return false;
if (id != null ? !id.equals(world.id) : world.id != null) return false;
return !(name != null ? !name.equals(world.name) : world.name != null);
}
if (moons != world.moons)
return false;
if (id != null ? !id.equals(world.id) : world.id != null)
return false;
return !(name != null ? !name.equals(world.name) : world.name != null);
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + moons;
return result;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + moons;
return result;
}
@Override
public String toString() {
return String.format("World{name='%s', moons=%d}", name, moons);
}
@Override
public String toString() {
return String.format("World{name='%s', moons=%d}", name, moons);
}
}

View File

@@ -26,12 +26,12 @@ import org.springframework.stereotype.Repository;
@Repository
public interface WorldRepository extends Neo4jRepository<World, Long> {
@Query("MATCH (n:World) SET n.updated=timestamp()")
void touchAllWorlds();
@Query("MATCH (n:World) SET n.updated=timestamp()")
void touchAllWorlds();
@Query("MATCH (n:World) SET n.updated=timestamp()")
Result touchAllWorldsWithStatistics();
@Query("MATCH (n:World) SET n.updated=timestamp()")
Result touchAllWorldsWithStatistics();
World findByName(String name);
World findByName(String name);
}

View File

@@ -40,11 +40,9 @@ import org.springframework.transaction.annotation.Transactional;
@Transactional
public class GalaxyService {
@Autowired
private WorldRepository worldRepository;
@Autowired private WorldRepository worldRepository;
@Autowired
Session session;
@Autowired Session session;
public long getNumberOfWorlds() {
return worldRepository.count();
@@ -93,13 +91,13 @@ public class GalaxyService {
mars.addRocketRouteTo(earth);
// todo: handle bi-directional automatically
//earth.addRocketRouteTo(mars);
// earth.addRocketRouteTo(mars);
// this is a bit silly
worldRepository.save(mars);
// todo: handle-bidirectional automatically
//worldRepository.save(earth);
// worldRepository.save(earth);
worlds.add(earth);
worlds.add(mars);
@@ -167,7 +165,6 @@ public class GalaxyService {
return session.loadAll(World.class, new Filter(propertyName, ComparisonOperator.EQUALS, propertyValue), depth);
}
public Iterable<World> findAllWorlds(Pagination paging) {
return session.loadAll(World.class, paging, 0);
}

View File

@@ -43,18 +43,16 @@ import org.springframework.web.context.WebApplicationContext;
* @author Vince Bickers
* @author Mark Angrish
*/
@ContextConfiguration(classes = {WebConfiguration.class, JSR303Tests.JSR303Context.class})
@ContextConfiguration(classes = { WebConfiguration.class, JSR303Tests.JSR303Context.class })
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class JSR303Tests extends MultiDriverTestClass {
private static final ObjectMapper objectMapper = new ObjectMapper();
@Autowired
private AdultService service;
@Autowired private AdultService service;
@Autowired
WebApplicationContext wac;
@Autowired WebApplicationContext wac;
private MockMvc mockMvc;
@@ -69,11 +67,7 @@ public class JSR303Tests extends MultiDriverTestClass {
Adult adult = new Adult("Peter", 18);
String json = objectMapper.writeValueAsString(adult);
mockMvc.perform(
post("/adults")
.contentType(MediaType.APPLICATION_JSON)
.content(json))
.andExpect(status().isOk());
mockMvc.perform(post("/adults").contentType(MediaType.APPLICATION_JSON).content(json)).andExpect(status().isOk());
}
@Test
@@ -82,10 +76,7 @@ public class JSR303Tests extends MultiDriverTestClass {
Adult adult = new Adult("Peter", 16);
String json = objectMapper.writeValueAsString(adult);
mockMvc.perform(
post("/adults")
.contentType(MediaType.APPLICATION_JSON)
.content(json))
mockMvc.perform(post("/adults").contentType(MediaType.APPLICATION_JSON).content(json))
.andExpect(status().isBadRequest());
}
@@ -95,10 +86,7 @@ public class JSR303Tests extends MultiDriverTestClass {
Adult adult = new Adult(null, 21);
String json = objectMapper.writeValueAsString(adult);
mockMvc.perform(
post("/adults")
.contentType(MediaType.APPLICATION_JSON)
.content(json))
mockMvc.perform(post("/adults").contentType(MediaType.APPLICATION_JSON).content(json))
.andExpect(status().isBadRequest());
}
@@ -108,15 +96,12 @@ public class JSR303Tests extends MultiDriverTestClass {
Adult adult = new Adult("A", 21);
String json = objectMapper.writeValueAsString(adult);
mockMvc.perform(
post("/adults")
.contentType(MediaType.APPLICATION_JSON)
.content(json))
mockMvc.perform(post("/adults").contentType(MediaType.APPLICATION_JSON).content(json))
.andExpect(status().isBadRequest());
}
@Configuration
@ComponentScan(basePackageClasses = {AdultService.class})
@ComponentScan(basePackageClasses = { AdultService.class })
@EnableNeo4jRepositories("org.springframework.data.neo4j.examples.jsr303.repo")
@EnableTransactionManagement
static class JSR303Context {
@@ -128,7 +113,8 @@ public class JSR303Tests extends MultiDriverTestClass {
@Bean
public SessionFactory sessionFactory() {
return new SessionFactory(getBaseConfiguration().build(),"org.springframework.data.neo4j.examples.jsr303.domain");
return new SessionFactory(getBaseConfiguration().build(),
"org.springframework.data.neo4j.examples.jsr303.domain");
}
}

View File

@@ -24,13 +24,13 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
* @author Vince Bickers
*/
@Configuration
@ComponentScan({"org.springframework.data.neo4j.examples.jsr303.controller"})
@ComponentScan({ "org.springframework.data.neo4j.examples.jsr303.controller" })
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {
@Bean(name="validator")
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
@Bean(name = "validator")
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
}

View File

@@ -13,16 +13,21 @@
package org.springframework.data.neo4j.examples.jsr303.controller;
import javax.validation.Valid;
import javax.validation.ValidationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.neo4j.examples.jsr303.domain.Adult;
import org.springframework.data.neo4j.examples.jsr303.service.AdultService;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.ValidationException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
/**
* @author Vince Bickers
@@ -30,22 +35,21 @@ import javax.validation.ValidationException;
@Controller
public class AdultController {
@Autowired
private AdultService service;
@Autowired private AdultService service;
@RequestMapping(value = "/adults", method = RequestMethod.POST, consumes = "application/json")
@ResponseBody
public Adult create (@Valid @RequestBody Adult entity, BindingResult bindingResult) {
// in practice we'd do a bit more than this...
if (bindingResult.hasErrors()) {
throw new ValidationException("oops");
}
return service.save(entity);
}
@RequestMapping(value = "/adults", method = RequestMethod.POST, consumes = "application/json")
@ResponseBody
public Adult create(@Valid @RequestBody Adult entity, BindingResult bindingResult) {
// in practice we'd do a bit more than this...
if (bindingResult.hasErrors()) {
throw new ValidationException("oops");
}
return service.save(entity);
}
@ExceptionHandler(ValidationException.class)
@ResponseBody
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public void handleException(ValidationException ve) { }
@ExceptionHandler(ValidationException.class)
@ResponseBody
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public void handleException(ValidationException ve) {}
}

View File

@@ -27,20 +27,15 @@ import org.neo4j.ogm.annotation.NodeEntity;
@NodeEntity
public class Adult {
@GraphId
private Long id;
@GraphId private Long id;
@NotNull @Size(min = 2, max = 50)
private String name;
@NotNull @Size(min = 2, max = 50) private String name;
@Min(18)
private Integer age;
@Min(18) private Integer age;
@AssertTrue
private boolean votingAge;
@AssertTrue private boolean votingAge;
public Adult() {
}
public Adult() {}
public Adult(String name, Integer age) {
this.name = name;
@@ -48,7 +43,6 @@ public class Adult {
this.votingAge = true;
}
public String getName() {
return name;
}

View File

@@ -21,5 +21,4 @@ import org.springframework.stereotype.Repository;
* @author Vince Bickers
*/
@Repository
public interface AdultRepository extends Neo4jRepository<Adult, Long> {
}
public interface AdultRepository extends Neo4jRepository<Adult, Long> {}

View File

@@ -24,10 +24,9 @@ import org.springframework.stereotype.Service;
@Service
public class AdultService {
@Autowired
private AdultRepository repository;
@Autowired private AdultRepository repository;
public Adult save(Adult adult) {
return repository.save(adult);
}
public Adult save(Adult adult) {
return repository.save(adult);
}
}

View File

@@ -16,7 +16,14 @@ package org.springframework.data.neo4j.examples.movies;
import static org.junit.Assert.*;
import static org.neo4j.ogm.testutil.GraphTestUtils.*;
import java.util.*;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -33,14 +40,26 @@ import org.neo4j.ogm.session.SessionFactory;
import org.neo4j.ogm.testutil.MultiDriverTestClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataAccessException;
import org.springframework.data.neo4j.examples.movies.domain.*;
import org.springframework.data.neo4j.examples.movies.repo.*;
import org.springframework.data.neo4j.examples.movies.domain.Actor;
import org.springframework.data.neo4j.examples.movies.domain.Cinema;
import org.springframework.data.neo4j.examples.movies.domain.Genre;
import org.springframework.data.neo4j.examples.movies.domain.Movie;
import org.springframework.data.neo4j.examples.movies.domain.Rating;
import org.springframework.data.neo4j.examples.movies.domain.ReleasedMovie;
import org.springframework.data.neo4j.examples.movies.domain.TempMovie;
import org.springframework.data.neo4j.examples.movies.domain.User;
import org.springframework.data.neo4j.examples.movies.repo.AbstractAnnotatedEntityRepository;
import org.springframework.data.neo4j.examples.movies.repo.AbstractEntityRepository;
import org.springframework.data.neo4j.examples.movies.repo.ActorRepository;
import org.springframework.data.neo4j.examples.movies.repo.CinemaRepository;
import org.springframework.data.neo4j.examples.movies.repo.RatingRepository;
import org.springframework.data.neo4j.examples.movies.repo.TempMovieRepository;
import org.springframework.data.neo4j.examples.movies.repo.UserRepository;
import org.springframework.data.neo4j.examples.movies.service.UserService;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.transaction.Neo4jTransactionManager;
@@ -60,32 +79,22 @@ import org.springframework.transaction.support.TransactionTemplate;
* @author Mark Paluch
* @author Jens Schauder
*/
@ContextConfiguration(classes = {MoviesIntegrationTests.MoviesContext.class})
@ContextConfiguration(classes = { MoviesIntegrationTests.MoviesContext.class })
@RunWith(SpringJUnit4ClassRunner.class)
public class MoviesIntegrationTests extends MultiDriverTestClass {
private final Logger logger = LoggerFactory.getLogger(MoviesIntegrationTests.class);
@Autowired
PlatformTransactionManager platformTransactionManager;
@Autowired
private Session session;
@Autowired
private UserRepository userRepository;
@Autowired
private UserService userService;
@Autowired
private CinemaRepository cinemaRepository;
@Autowired
private AbstractAnnotatedEntityRepository abstractAnnotatedEntityRepository;
@Autowired
private AbstractEntityRepository abstractEntityRepository;
@Autowired
private TempMovieRepository tempMovieRepository;
@Autowired
private ActorRepository actorRepository;
@Autowired
private RatingRepository ratingRepository;
@Autowired PlatformTransactionManager platformTransactionManager;
@Autowired private Session session;
@Autowired private UserRepository userRepository;
@Autowired private UserService userService;
@Autowired private CinemaRepository cinemaRepository;
@Autowired private AbstractAnnotatedEntityRepository abstractAnnotatedEntityRepository;
@Autowired private AbstractEntityRepository abstractEntityRepository;
@Autowired private TempMovieRepository tempMovieRepository;
@Autowired private ActorRepository actorRepository;
@Autowired private RatingRepository ratingRepository;
private TransactionTemplate transactionTemplate;
@@ -111,7 +120,6 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
assertSameGraph(getGraphDatabaseService(), "CREATE (u:User:Person)");
}
@Test
public void shouldSaveReleasedMovie() {
@@ -124,8 +132,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
abstractAnnotatedEntityRepository.save(releasedMovie);
assertSameGraph(getGraphDatabaseService(),
"CREATE (m:ReleasedMovie:AbstractAnnotatedEntity {cinemaRelease:'1994-09-10T00:00:00.000Z'," +
"cannesRelease:768700800000,title:'Pulp Fiction'})");
"CREATE (m:ReleasedMovie:AbstractAnnotatedEntity {cinemaRelease:'1994-09-10T00:00:00.000Z',"
+ "cannesRelease:768700800000,title:'Pulp Fiction'})");
}
@Test
@@ -145,14 +153,14 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
public void shouldSaveMovie() {
Movie movie = new Movie("Pulp Fiction");
movie.setTags(new String[]{"cool", "classic"});
movie.setImage(new byte[]{1, 2, 3});
movie.setTags(new String[] { "cool", "classic" });
movie.setImage(new byte[] { 1, 2, 3 });
abstractEntityRepository.save(movie);
// byte arrays have to be transferred with a JSON-supported format. Base64 is the default.
assertSameGraph(getGraphDatabaseService(), "CREATE (m:Movie {name:'Pulp Fiction', tags:['cool','classic'], " +
"image:'AQID'})");
assertSameGraph(getGraphDatabaseService(),
"CREATE (m:Movie {name:'Pulp Fiction', tags:['cool','classic'], " + "image:'AQID'})");
}
@Test
@@ -170,12 +178,10 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
}
});
assertSameGraph(getGraphDatabaseService(), "CREATE (:User:Person {name:'Michal'})," +
"(:User:Person {name:'Vince'})," +
"(:User:Person {name:'Adam'})");
assertSameGraph(getGraphDatabaseService(),
"CREATE (:User:Person {name:'Michal'})," + "(:User:Person {name:'Vince'})," + "(:User:Person {name:'Adam'})");
}
@Test
public void shouldSaveUsers2() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@@ -191,9 +197,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
}
});
assertSameGraph(getGraphDatabaseService(), "CREATE (:User:Person {name:'Michal'})," +
"(:User:Person {name:'Vince'})," +
"(:User:Person {name:'Adam'})");
assertSameGraph(getGraphDatabaseService(),
"CREATE (:User:Person {name:'Michal'})," + "(:User:Person {name:'Vince'})," + "(:User:Person {name:'Adam'})");
}
@Test
@@ -210,16 +215,15 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
assertSameGraph(getGraphDatabaseService(), "CREATE (u:User:Person {name:'Adam'})");
}
@Test
@Ignore // FIXME
@Ignore // FIXME
// this test expects the session/tx to check for dirty objects, which it currently does not do
// you must save objects explicitly.
public void shouldUpdateUserUsingTransactionalService() {
User user = new User("Michal");
userRepository.save(user);
userService.updateUser(user, "Adam"); //notice userRepository.save(..) isn't called,
userService.updateUser(user, "Adam"); // notice userRepository.save(..) isn't called,
// not even in the service impl!
assertSameGraph(getGraphDatabaseService(), "CREATE (u:User {name:'Adam'})");
@@ -261,7 +265,6 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
User user = new User();
userRepository.save(user);
Optional<User> loaded = userRepository.findById(user.getId());
assertTrue(loaded.isPresent());
@@ -298,7 +301,6 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
}
}
@Test
public void shouldHandleMultipleConcurrentRequests() throws InterruptedException, Neo4jFailedToStartException {
@@ -324,7 +326,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
@Test(expected = DataAccessException.class)
public void shouldInterceptOGMExceptions() {
ratingRepository.findAll(0); // ratings are REs and must be found to at least depth 1 in order to get the start and end nodes
ratingRepository.findAll(0); // ratings are REs and must be found to at least depth 1 in order to get the start and
// end nodes
}
@Test
@@ -334,7 +337,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
userRepository.save(user);
assertSameGraph(getGraphDatabaseService(), "CREATE (u:User:Person {name:'Michal'})-[:INTERESTED]->(g:Genre {name:'Drama'})");
assertSameGraph(getGraphDatabaseService(),
"CREATE (u:User:Person {name:'Michal'})-[:INTERESTED]->(g:Genre {name:'Drama'})");
}
@Test
@@ -346,14 +350,10 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
userRepository.save(user);
assertSameGraph(getGraphDatabaseService(), "CREATE " +
"(u:User:Person {name:'Michal'})," +
"(g1:Genre {name:'Drama'})," +
"(g2:Genre {name:'Historical'})," +
"(g3:Genre {name:'Thriller'})," +
"(u)-[:INTERESTED]->(g1)," +
"(u)-[:INTERESTED]->(g2)," +
"(u)-[:INTERESTED]->(g3)");
assertSameGraph(getGraphDatabaseService(),
"CREATE " + "(u:User:Person {name:'Michal'})," + "(g1:Genre {name:'Drama'}),"
+ "(g2:Genre {name:'Historical'})," + "(g3:Genre {name:'Thriller'})," + "(u)-[:INTERESTED]->(g1),"
+ "(u)-[:INTERESTED]->(g2)," + "(u)-[:INTERESTED]->(g3)");
}
@Test
@@ -363,7 +363,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
userRepository.save(user, 1);
assertSameGraph(getGraphDatabaseService(), "CREATE (u:User:Person {name:'Michal'})-[:INTERESTED]->(g:Genre {name:'Drama'})");
assertSameGraph(getGraphDatabaseService(),
"CREATE (u:User:Person {name:'Michal'})-[:INTERESTED]->(g:Genre {name:'Drama'})");
}
@Test
@@ -384,15 +385,11 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
}
});
assertSameGraph(getGraphDatabaseService(), "CREATE " +
"(m:User:Person {name:'Michal'})," +
"(v:User:Person {name:'Vince'})," +
"(g:Genre {name:'Drama'})," +
"(m)-[:INTERESTED]->(g)," +
"(v)-[:INTERESTED]->(g)");
assertSameGraph(getGraphDatabaseService(),
"CREATE " + "(m:User:Person {name:'Michal'})," + "(v:User:Person {name:'Vince'})," + "(g:Genre {name:'Drama'}),"
+ "(m)-[:INTERESTED]->(g)," + "(v)-[:INTERESTED]->(g)");
}
@Test
public void shouldSaveUserButNotGenre() {
User user = new User("Michal");
@@ -421,13 +418,10 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
}
});
assertSameGraph(getGraphDatabaseService(), "CREATE " +
"(m:User:Person {name:'Michal'})," +
"(g:Genre {name:'New Drama'})," +
"(m)-[:INTERESTED]->(g)");
assertSameGraph(getGraphDatabaseService(),
"CREATE " + "(m:User:Person {name:'Michal'})," + "(g:Genre {name:'New Drama'})," + "(m)-[:INTERESTED]->(g)");
}
@Test
public void shouldRemoveGenreFromUser() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@@ -445,9 +439,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
}
});
assertSameGraph(getGraphDatabaseService(), "CREATE " +
"(m:User:Person {name:'Michal'})," +
"(g:Genre {name:'Drama'})");
assertSameGraph(getGraphDatabaseService(),
"CREATE " + "(m:User:Person {name:'Michal'})," + "(g:Genre {name:'Drama'})");
}
@Test
@@ -465,12 +458,10 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
}
});
assertSameGraph(getGraphDatabaseService(), "CREATE " +
"(m:User:Person {name:'Michal'})," +
"(g:Genre {name:'Drama'})");
assertSameGraph(getGraphDatabaseService(),
"CREATE " + "(m:User:Person {name:'Michal'})," + "(g:Genre {name:'Drama'})");
}
@Test
public void shouldAddNewVisitorToCinema() {
Cinema cinema = new Cinema("Odeon");
@@ -478,10 +469,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
cinemaRepository.save(cinema);
assertSameGraph(getGraphDatabaseService(), "CREATE " +
"(m:User:Person {name:'Michal'})," +
"(c:Theatre {name:'Odeon', capacity:0})," +
"(m)-[:VISITED]->(c)");
assertSameGraph(getGraphDatabaseService(), "CREATE " + "(m:User:Person {name:'Michal'}),"
+ "(c:Theatre {name:'Odeon', capacity:0})," + "(m)-[:VISITED]->(c)");
}
@Test
@@ -499,10 +488,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
}
});
assertSameGraph(getGraphDatabaseService(), "CREATE " +
"(m:User:Person {name:'Michal'})," +
"(c:Theatre {name:'Odeon', capacity:0})," +
"(m)-[:VISITED]->(c)");
assertSameGraph(getGraphDatabaseService(), "CREATE " + "(m:User:Person {name:'Michal'}),"
+ "(c:Theatre {name:'Odeon', capacity:0})," + "(m)-[:VISITED]->(c)");
}
@Test
@@ -517,9 +504,11 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
});
try {
assertSameGraph(getGraphDatabaseService(), "CREATE (m:User {name:'Michal'})-[:FRIEND_OF]->(a:User:Person {name:'Adam'})");
assertSameGraph(getGraphDatabaseService(),
"CREATE (m:User {name:'Michal'})-[:FRIEND_OF]->(a:User:Person {name:'Adam'})");
} catch (AssertionError error) {
assertSameGraph(getGraphDatabaseService(), "CREATE (m:User:Person {name:'Michal'})<-[:FRIEND_OF]-(a:User:Person {name:'Adam'})");
assertSameGraph(getGraphDatabaseService(),
"CREATE (m:User:Person {name:'Michal'})<-[:FRIEND_OF]-(a:User:Person {name:'Adam'})");
}
}
@@ -564,8 +553,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
User michal = ((Iterable<User>) findByProperty(User.class, "name", "Michal")).iterator().next();
assertSameGraph(getGraphDatabaseService(), "CREATE (u:User:Person {name:'Michal'})-[:RATED {stars:5, " +
"comment:'Best movie ever', ratingTimestamp:0}]->(m:Movie {name:'Pulp Fiction'})");
assertSameGraph(getGraphDatabaseService(), "CREATE (u:User:Person {name:'Michal'})-[:RATED {stars:5, "
+ "comment:'Best movie ever', ratingTimestamp:0}]->(m:Movie {name:'Pulp Fiction'})");
}
@Test
@@ -575,15 +564,16 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
TempMovie movie = new TempMovie("Pulp Fiction");
//Save the movie
// Save the movie
movie = tempMovieRepository.save(movie);
//Create a new user and rate an existing movie
// Create a new user and rate an existing movie
User user = new User("Michal");
user.rate(movie, 5, "Best movie ever");
userRepository.save(user);
TempMovie tempMovie = ((Iterable<TempMovie>) findByProperty(TempMovie.class, "name", "Pulp Fiction")).iterator().next();
TempMovie tempMovie = ((Iterable<TempMovie>) findByProperty(TempMovie.class, "name", "Pulp Fiction")).iterator()
.next();
assertEquals(1, tempMovie.getRatings().size());
}
});
@@ -668,7 +658,7 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
}
protected Iterable<?> findByProperty(Class clazz, String propertyName, Object propertyValue) {
return session.loadAll(clazz, new Filter(propertyName, ComparisonOperator.EQUALS, propertyValue));
return session.loadAll(clazz, new Filter(propertyName, ComparisonOperator.EQUALS, propertyValue));
}
//
@@ -680,7 +670,7 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
}
@Configuration
@ComponentScan({"org.springframework.data.neo4j.examples.movies.service"})
@ComponentScan({ "org.springframework.data.neo4j.examples.movies.service" })
@EnableNeo4jRepositories("org.springframework.data.neo4j.examples.movies.repo")
@EnableTransactionManagement
static class MoviesContext {
@@ -692,7 +682,8 @@ public class MoviesIntegrationTests extends MultiDriverTestClass {
@Bean
public SessionFactory sessionFactory() {
return new SessionFactory(getBaseConfiguration().build(), "org.springframework.data.neo4j.examples.movies.domain");
return new SessionFactory(getBaseConfiguration().build(),
"org.springframework.data.neo4j.examples.movies.domain");
}
}
}

View File

@@ -22,6 +22,5 @@ import org.neo4j.ogm.annotation.NodeEntity;
@NodeEntity
public abstract class AbstractAnnotatedEntity {
@GraphId
Long nodeId;
@GraphId Long nodeId;
}

View File

@@ -19,9 +19,9 @@ package org.springframework.data.neo4j.examples.movies.domain;
*/
public abstract class AbstractEntity {
Long id;
Long id;
public Long getId() {
return id;
}
public Long getId() {
return id;
}
}

View File

@@ -13,40 +13,37 @@
package org.springframework.data.neo4j.examples.movies.domain;
import org.neo4j.ogm.annotation.GraphId;
/**
* @author Michal Bachman
*/
public class Actor{
public class Actor {
@GraphId
Long nodeId;
String id;
String name;
@GraphId Long nodeId;
String id;
String name;
public Actor() {
}
public Actor() {}
public Actor(String id, String name) {
this.id = id;
this.name = name;
}
public Actor(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -13,13 +13,13 @@
package org.springframework.data.neo4j.examples.movies.domain;
import java.util.HashSet;
import java.util.Set;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Property;
import org.neo4j.ogm.annotation.Relationship;
import java.util.HashSet;
import java.util.Set;
/**
* @author Michal Bachman
* @author Luanne Misquitta
@@ -31,19 +31,15 @@ public class Cinema {
private Long id;
private String name;
@Property(name = "city")
private String location;
@Property(name = "city") private String location;
@Relationship(type = "VISITED", direction = Relationship.INCOMING)
private Set<User> visited = new HashSet<>();
@Relationship(type = "VISITED", direction = Relationship.INCOMING) private Set<User> visited = new HashSet<>();
@Relationship(type = "BLOCKBUSTER", direction = Relationship.OUTGOING)
private TempMovie blockbusterOfTheWeek;
@Relationship(type = "BLOCKBUSTER", direction = Relationship.OUTGOING) private TempMovie blockbusterOfTheWeek;
private int capacity;
public Cinema() {
}
public Cinema() {}
public Cinema(String name) {
this.name = name;
@@ -92,8 +88,10 @@ public class Cinema {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Cinema cinema = (Cinema) o;

View File

@@ -21,6 +21,8 @@ package org.springframework.data.neo4j.examples.movies.domain;
public interface CinemaAndBlockbuster {
String getName();
String getLocation();
TempMovie getBlockbusterOfTheWeek();
}

View File

@@ -23,6 +23,7 @@ import org.springframework.beans.factory.annotation.Value;
public interface CinemaAndBlockbusterName {
Long getId();
String getName();
@Value("#{target.blockbusterOfTheWeek.name}")

View File

@@ -20,6 +20,5 @@ public class Director extends Person {
private Long id;
public Director() {
}
public Director() {}
}

View File

@@ -18,25 +18,24 @@ package org.springframework.data.neo4j.examples.movies.domain;
*/
public class Genre {
private Long id;
private String name;
private Long id;
private String name;
public Genre() {
}
public Genre() {}
public Genre(String name) {
this.name = name;
}
public Genre(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -18,34 +18,33 @@ package org.springframework.data.neo4j.examples.movies.domain;
*/
public class Movie extends AbstractEntity {
private String name;
private String[] tags;
private byte[] image;
private String name;
private String[] tags;
private byte[] image;
public Movie() {
}
public Movie() {}
public Movie(String name) {
this.name = name;
}
public Movie(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public String[] getTags() {
return tags;
}
public String[] getTags() {
return tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
public byte[] getImage() {
return image;
}
public byte[] getImage() {
return image;
}
public void setImage(byte[] image) {
this.image = image;
}
public void setImage(byte[] image) {
this.image = image;
}
}

View File

@@ -21,7 +21,6 @@ public class Person {
private String name;
public String getName() {
return name;
}
@@ -36,8 +35,10 @@ public class Person {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Person person = (Person) o;

View File

@@ -21,77 +21,75 @@ import org.neo4j.ogm.annotation.StartNode;
* @author Michal Bachman
*/
@RelationshipEntity(type = "RATED")
public class Rating implements Comparable{
private Long id;
public class Rating implements Comparable {
private Long id;
@StartNode
private User user;
@EndNode
private TempMovie movie;
private int stars;
private String comment;
@StartNode private User user;
@EndNode private TempMovie movie;
private int stars;
private String comment;
private long ratingTimestamp;
private long ratingTimestamp;
public Rating() {}
public Rating() {}
public Rating(User user, TempMovie movie, int stars, String comment) {
this.user = user;
this.movie = movie;
this.stars = stars;
this.comment = comment;
}
public Rating(User user, TempMovie movie, int stars, String comment) {
this.user = user;
this.movie = movie;
this.stars = stars;
this.comment = comment;
}
public Long getId() {
return id;
}
public Long getId() {
return id;
}
public void setUser(User user) {
this.user = user;
}
public void setUser(User user) {
this.user = user;
}
public void setMovie(TempMovie movie) {
this.movie = movie;
}
public void setMovie(TempMovie movie) {
this.movie = movie;
}
public void setStars(int stars) {
this.stars = stars;
}
public void setStars(int stars) {
this.stars = stars;
}
public void setComment(String comment) {
this.comment = comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public User getUser() {
return user;
}
public User getUser() {
return user;
}
public TempMovie getMovie() {
return movie;
}
public TempMovie getMovie() {
return movie;
}
public int getStars() {
return stars;
}
public int getStars() {
return stars;
}
public String getComment() {
return comment;
}
public String getComment() {
return comment;
}
public long getRatingTimestamp() {
return ratingTimestamp;
}
public long getRatingTimestamp() {
return ratingTimestamp;
}
public void setRatingTimestamp(long ratingTimestamp) {
this.ratingTimestamp = ratingTimestamp;
}
public void setRatingTimestamp(long ratingTimestamp) {
this.ratingTimestamp = ratingTimestamp;
}
@Override
public int compareTo(Object o) {
Rating other = (Rating) o;
if (stars == ((Rating) o).getStars()) {
return getUser().getName().compareTo(other.getUser().getName());
}
return stars - other.getStars();
}
@Override
public int compareTo(Object o) {
Rating other = (Rating) o;
if (stars == ((Rating) o).getStars()) {
return getUser().getName().compareTo(other.getUser().getName());
}
return stars - other.getStars();
}
}

View File

@@ -13,43 +13,40 @@
package org.springframework.data.neo4j.examples.movies.domain;
import java.util.Date;
import org.neo4j.ogm.annotation.Property;
import org.neo4j.ogm.annotation.typeconversion.DateLong;
import java.util.Date;
/**
* @author Michal Bachman
*/
//the fields here will move to Movie, this separate class exists temporarily after its tests pass
// the fields here will move to Movie, this separate class exists temporarily after its tests pass
public class ReleasedMovie extends AbstractAnnotatedEntity {
private String title;
private String title;
@Property(name = "cinemaRelease")
private Date released;
@Property(name = "cinemaRelease") private Date released;
@DateLong
private Date cannesRelease;
@DateLong private Date cannesRelease;
public ReleasedMovie() {
}
public ReleasedMovie() {}
public ReleasedMovie(String title, Date released, Date cannesRelease) {
this.title = title;
this.released = released;
this.cannesRelease = cannesRelease;
}
public ReleasedMovie(String title, Date released, Date cannesRelease) {
this.title = title;
this.released = released;
this.cannesRelease = cannesRelease;
}
public String getTitle() {
return title;
}
public String getTitle() {
return title;
}
public Date getReleased() {
return released;
}
public Date getReleased() {
return released;
}
public Date getCannesRelease() {
return cannesRelease;
}
public Date getCannesRelease() {
return cannesRelease;
}
}

View File

@@ -13,40 +13,38 @@
package org.springframework.data.neo4j.examples.movies.domain;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
import java.util.HashSet;
import java.util.Set;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
/**
* @author Michal Bachman
* @author Luanne Misquitta
*/
//todo merge with movie when tests fixed
// todo merge with movie when tests fixed
@NodeEntity(label = "Movie")
public class TempMovie extends AbstractEntity {
private String name;
@Relationship(type = "RATED", direction = Relationship.INCOMING)
private Set<Rating> ratings = new HashSet<>();
private String name;
@Relationship(type = "RATED", direction = Relationship.INCOMING) private Set<Rating> ratings = new HashSet<>();
public TempMovie() {
}
public TempMovie() {}
public TempMovie(String name) {
this.name = name;
}
public TempMovie(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void addRating(Rating rating) {
ratings.add(rating);
}
public void addRating(Rating rating) {
ratings.add(rating);
}
public Set<Rating> getRatings() {
return ratings;
}
public Set<Rating> getRatings() {
return ratings;
}
}

View File

@@ -13,80 +13,76 @@
package org.springframework.data.neo4j.examples.movies.domain;
import org.neo4j.ogm.annotation.Relationship;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.neo4j.ogm.annotation.Relationship;
/**
* @author Michal Bachman
* @author Luanne Misquitta
*/
public class User extends Person{
public class User extends Person {
private String middleName;
private String surname;
private String middleName;
private String surname;
private Collection<Genre> interested = new HashSet<>();
private Collection<Genre> interested = new HashSet<>();
@Relationship(type = "FRIEND_OF", direction = Relationship.UNDIRECTED)
private Collection<User> friends = new HashSet<>();
@Relationship(type = "FRIEND_OF",
direction = Relationship.UNDIRECTED) private Collection<User> friends = new HashSet<>();
@Relationship(type = "RATED")
private Set<Rating> ratings = new HashSet<>();
@Relationship(type = "RATED") private Set<Rating> ratings = new HashSet<>();
public User() {
}
public User() {}
public User(String name) {
setName(name);
}
public User(String name) {
setName(name);
}
public User(String name, String surname) {
setName(name);
this.surname = surname;
}
public User(String name, String surname) {
setName(name);
this.surname = surname;
}
public void interestedIn(Genre genre) {
interested.add(genre);
}
public void interestedIn(Genre genre) {
interested.add(genre);
}
public void notInterestedIn(Genre genre) {
interested.remove(genre);
}
public void notInterestedIn(Genre genre) {
interested.remove(genre);
}
public void befriend(User user) {
friends.add(user);
user.friends.add(this);
}
public void befriend(User user) {
friends.add(user);
user.friends.add(this);
}
public Rating rate(TempMovie movie, int stars, String comment) {
Rating rating = new Rating(this, movie, stars, comment);
movie.addRating(rating);
ratings.add(rating);
return rating;
}
public Rating rate(TempMovie movie, int stars, String comment) {
Rating rating = new Rating(this, movie, stars, comment);
movie.addRating(rating);
ratings.add(rating);
return rating;
}
public Collection<User> getFriends() {
return friends;
}
public Collection<User> getFriends() {
return friends;
}
public String getMiddleName() {
return middleName;
}
public String getMiddleName()
{
return middleName;
}
public Set<Rating> getRatings() {
return ratings;
}
public Set<Rating> getRatings() {
return ratings;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getSurname() {
return surname;
}
public String getSurname() {
return surname;
}
}

View File

@@ -23,25 +23,24 @@ import org.springframework.data.neo4j.annotation.QueryResult;
@QueryResult
public class CinemaQueryResult {
private Long id;
private String name;
private Long id;
private String name;
public CinemaQueryResult() {
}
public CinemaQueryResult() {}
public Long getId() {
return id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}

Some files were not shown because too many files have changed in this diff Show More