DATAGRAPH-1358 - Add support for configuring SDN 6 in a CDI context.
This brings in a new `Neo4jCdiExtension` as part of the `config` package being public API. This extension is loaded via Java SPI interface by CDI containers. It can also be used explicitly. The extension is responsible for registering a producer of Neo4j related beans and also one `Neo4jRepositoryFactoryCdiBean` for each repository type discovered by Spring Data's CDI extension itself. The task of the internal API `Neo4jRepositoryFactoryCdiBean` is getting the required beans from the CDI context and create the standard `Neo4jRepositoryFactory`, nothing more. The new `Neo4jCdiConfigurationSupport` is an internal, application scoped API that produces a couple of required beans qualified as `Builtin` (a custom CDI qualifiers). Those can be overwritten by non-qualified beans of the same type by a user. In addition to those changes, the PR also fixes the name of `AbstractNeo4jConfig#databaseSelectionProvider()` to bring symmetry to the API. Unrelated to all of that, the `Neo4jConnectionSupport` in the `Neo4jExtension` has been fixed to not expose the volatile driver API, which caused the initial draft of `Neo4jCdiExtensionIT` to fail.
This commit is contained in:
17
pom.xml
17
pom.xml
@@ -77,6 +77,7 @@
|
||||
<changelist>-SNAPSHOT</changelist>
|
||||
<checkstyle.version>8.29</checkstyle.version>
|
||||
<cypher-dsl.version>2020.0.1</cypher-dsl.version>
|
||||
<cdi>2.0</cdi>
|
||||
<dist.id>spring-data-neo4j</dist.id>
|
||||
<dist.key>SDNEO4J</dist.key>
|
||||
<flatten-maven-plugin.version>1.2.1</flatten-maven-plugin.version>
|
||||
@@ -406,6 +407,20 @@
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.enterprise</groupId>
|
||||
<artifactId>cdi-api</artifactId>
|
||||
<version>${cdi}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.weld.se</groupId>
|
||||
<artifactId>weld-se-core</artifactId>
|
||||
<version>3.1.4.Final</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -641,7 +656,7 @@
|
||||
<backend>html</backend>
|
||||
<doctype>book</doctype>
|
||||
<imagesDir>img</imagesDir>
|
||||
<sourceDirectory>${basedir}/docs</sourceDirectory>
|
||||
<sourceDirectory>${project.basedir}/src/main/asciidoc</sourceDirectory>
|
||||
<sourceDocumentName>index.adoc</sourceDocumentName>
|
||||
<sourceHighlighter>coderay</sourceHighlighter>
|
||||
<attributes>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
Here are a couple of more frequently asked question in addition to the ones in the <<what-is-sdn,preface>>.
|
||||
|
||||
[[faq.multidatabase]]
|
||||
== Neo4j 4.0 supports multiple databases - How can I use them?
|
||||
|
||||
You can either statically configure the database name or run your own database name provider.
|
||||
@@ -32,6 +33,15 @@ Here is a working example for an imperative application secured with Spring Secu
|
||||
[[faq.databaseSelectionProvider]]
|
||||
.Neo4jConfig.java
|
||||
----
|
||||
import org.neo4j.springframework.data.core.DatabaseSelection;
|
||||
import org.neo4j.springframework.data.core.DatabaseSelectionProvider;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
|
||||
include::../../../../src/test/java/org/springframework/data/neo4j/documentation/Neo4jConfig.java[tags=faq.multidatabase]
|
||||
----
|
||||
|
||||
@@ -208,3 +218,171 @@ movieExample = Example.of(
|
||||
);
|
||||
movies = this.movieRepository.findAll(movieExample);
|
||||
----
|
||||
|
||||
== Do I need Spring Boot to use Spring Data Neo4j?
|
||||
|
||||
No, you don't.
|
||||
While the automatic configuration of many Spring aspects through Spring Boot takes away a lot of manual cruft and is the recommended approach for setting up new Spring projects, you don't need to have to use this.
|
||||
|
||||
The following dependency is required for the solutions described above:
|
||||
|
||||
[source,xml,subs="verbatim,attributes"]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>{springGroupId}</groupId>
|
||||
<artifactId>{artifactId}</artifactId>
|
||||
<version>{spring-data-neo4j-version}</version>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
The coordinates for a Gradle setup are the same.
|
||||
|
||||
To select a different database - either statically or dynamically - you can add a Bean of type `DatabaseSelectionProvider` as explained in <<faq.multidatabase>>.
|
||||
For a reactive scenario, we provide `ReactiveDatabaseSelectionProvider`.
|
||||
|
||||
=== Using Spring Data Neo4j inside a Spring context without Spring Boot
|
||||
|
||||
We provide two abstract configuration classes to support you in bringing in the necessary beans: `AbstractNeo4jConfig` for imperative database access and `AbstractReactiveNeo4jConfig` for the reactive version.
|
||||
They are meant to be used with `@EnableNeo4jRepositories` and `@EnableReactiveNeo4jRepositories` respectively.
|
||||
See <<bootless-imperative-configuration>> and <<bootless-reactive-configuration>> for an example usage.
|
||||
Both classes require you to override `driver()` in which you are supposed to create the driver.
|
||||
|
||||
To get the imperative version of the <<neo4j-client,Neo4j client>>, the template and support for imperative repositories, use something similar as shown here:
|
||||
|
||||
[source,java]
|
||||
[[bootless-imperative-configuration]]
|
||||
.Enabling Spring Data Neo4j infrastructure for imperative database access
|
||||
----
|
||||
import org.neo4j.driver.Driver;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import org.springframework.data.neo4j.config.AbstractNeo4jConfig;
|
||||
import org.springframework.data.neo4j.core.DatabaseSelectionProvider;
|
||||
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
|
||||
|
||||
@Configuration
|
||||
@EnableNeo4jRepositories
|
||||
@EnableTransactionManagement
|
||||
class MyConfiguration extends AbstractNeo4jConfig {
|
||||
|
||||
@Override @Bean
|
||||
public Driver driver() { // <.>
|
||||
return GraphDatabase.driver("bolt://localhost:7687", AuthTokens.basic("neo4j", "secret"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<String> getMappingBasePackages() {
|
||||
return Collections.singletonList(Person.class.getPackage().getName());
|
||||
}
|
||||
|
||||
@Override @Bean // <.>
|
||||
protected DatabaseSelectionProvider databaseSelectionProvider() {
|
||||
|
||||
return DatabaseSelectionProvider.createStaticDatabaseSelectionProvider("yourDatabase");
|
||||
}
|
||||
}
|
||||
----
|
||||
<.> The driver bean is required.
|
||||
<.> This statically selects a database named `yourDatabase` and is *optional*.
|
||||
|
||||
The following listing provides the reactive Neo4j client and template, enables reactive transaction management and discovers Neo4j related repositories:
|
||||
|
||||
[source,java]
|
||||
[[bootless-reactive-configuration]]
|
||||
.Enabling Spring Data Neo4j infrastructure for reactive database access
|
||||
----
|
||||
import org.neo4j.driver.Driver;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.neo4j.config.AbstractReactiveNeo4jConfig;
|
||||
import org.springframework.data.neo4j.repository.config.EnableReactiveNeo4jRepositories;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@Configuration
|
||||
@EnableReactiveNeo4jRepositories
|
||||
@EnableTransactionManagement
|
||||
class MyConfiguration extends AbstractReactiveNeo4jConfig {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public Driver driver() {
|
||||
return GraphDatabase.driver("bolt://localhost:7687", AuthTokens.basic("neo4j", "secret"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<String> getMappingBasePackages() {
|
||||
return Collections.singletonList(Person.class.getPackage().getName());
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
=== Using Spring Data Neo4j in a CDI 2.0 environment
|
||||
|
||||
For your convenience we provide a CDI extension with `Neo4jCdiExtension`.
|
||||
When run in a compatible CDI 2.0 container, it will be automatically be registered and loaded through https://docs.oracle.com/javase/tutorial/ext/basics/spi.html[Java's service loader SPI].
|
||||
|
||||
The only thing you have to bring into your application is an annotated type that produces the Neo4j Java Driver:
|
||||
|
||||
[source,java]
|
||||
[[cdi-driver-producer]]
|
||||
.A CDI producer for the Neo4j Java Driver
|
||||
----
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.enterprise.inject.Disposes;
|
||||
import javax.enterprise.inject.Produces;
|
||||
|
||||
import org.neo4j.driver.AuthTokens;
|
||||
import org.neo4j.driver.Driver;
|
||||
import org.neo4j.driver.GraphDatabase;
|
||||
|
||||
public class Neo4jConfig {
|
||||
|
||||
@Produces @ApplicationScoped
|
||||
public Driver driver() { // <.>
|
||||
return GraphDatabase
|
||||
.driver("bolt://localhost:7687", AuthTokens.basic("neo4j", "secret"));
|
||||
}
|
||||
|
||||
public void close(@Disposes Driver driver) {
|
||||
driver.close();
|
||||
}
|
||||
|
||||
@Produces @Singleton
|
||||
public DatabaseSelectionProvider getDatabaseSelectionProvider() { // <.>
|
||||
return DatabaseSelectionProvider.createStaticDatabaseSelectionProvider("yourDatabase");
|
||||
}
|
||||
}
|
||||
----
|
||||
<.> Same as with plain Spring in <<bootless-imperative-configuration>>, but annotated with the corresponding CDI infrastructure.
|
||||
<.> This is *optional*. However, if you run a custom database selection provider, you _must_ not qualify this bean.
|
||||
|
||||
If you are running in a SE Container - like the one https://weld.cdi-spec.org[Weld] provides for example, you can enable the extension like that:
|
||||
|
||||
[source,java]
|
||||
[[cdi-driver-producer-se]]
|
||||
.Enabling the Neo4j CDI extension in a SE container
|
||||
----
|
||||
import javax.enterprise.inject.se.SeContainer;
|
||||
import javax.enterprise.inject.se.SeContainerInitializer;
|
||||
|
||||
import org.springframework.data.neo4j.config.Neo4jCdiExtension;
|
||||
|
||||
public class SomeClass {
|
||||
void someMethod() {
|
||||
try (SeContainer container = SeContainerInitializer.newInstance()
|
||||
.disableDiscovery()
|
||||
.addExtensions(Neo4jCdiExtension.class)
|
||||
.addBeanClasses(YourDriverFactory.class)
|
||||
.addPackages(Package.getPackage("your.domain.package"))
|
||||
.initialize()
|
||||
) {
|
||||
SomeRepository someRepository = container.select(SomeRepository.class).get();
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -24,7 +24,7 @@ include::{manualIncludeDir}/README.adoc[tags=properties]
|
||||
:springVersion: 5.2.0.RELEASE
|
||||
:spring-framework-docs: https://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference
|
||||
:spring-framework-javadoc: https://docs.spring.io/spring/docs/{springVersion}/javadoc-api
|
||||
:spring-data-commons-docs: ../../../../../other-spring-data/spring-data-commons/src/main/asciidoc/
|
||||
:spring-data-commons-docs: ../../../../../other-spring-data/spring-data-commons/src/main/asciidoc
|
||||
|
||||
(C) 2008-2020 The original authors.
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.neo4j.core.DatabaseSelectionProvider;
|
||||
import org.springframework.data.neo4j.core.Neo4jClient;
|
||||
import org.springframework.data.neo4j.core.Neo4jOperations;
|
||||
import org.springframework.data.neo4j.core.Neo4jTemplate;
|
||||
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
|
||||
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
|
||||
@@ -60,7 +61,7 @@ public abstract class AbstractNeo4jConfig extends Neo4jConfigurationSupport {
|
||||
}
|
||||
|
||||
@Bean(Neo4jRepositoryConfigurationExtension.DEFAULT_NEO4J_TEMPLATE_BEAN_NAME)
|
||||
public Neo4jTemplate neo4jTemplate(final Neo4jClient neo4jClient, final Neo4jMappingContext mappingContext,
|
||||
public Neo4jOperations neo4jTemplate(final Neo4jClient neo4jClient, final Neo4jMappingContext mappingContext,
|
||||
DatabaseSelectionProvider databaseNameProvider) {
|
||||
|
||||
return new Neo4jTemplate(neo4jClient, mappingContext, databaseNameProvider);
|
||||
@@ -86,7 +87,7 @@ public abstract class AbstractNeo4jConfig extends Neo4jConfigurationSupport {
|
||||
* Neo4j 3.5 and prior.
|
||||
*/
|
||||
@Bean
|
||||
protected DatabaseSelectionProvider neo4jDatabaseNameProvider() {
|
||||
protected DatabaseSelectionProvider databaseSelectionProvider() {
|
||||
|
||||
return DatabaseSelectionProvider.getDefaultSelectionProvider();
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public abstract class AbstractReactiveNeo4jConfig extends Neo4jConfigurationSupp
|
||||
* Neo4j 3.5 and prior.
|
||||
*/
|
||||
@Bean
|
||||
protected ReactiveDatabaseSelectionProvider reactiveNeo4jDatabaseNameProvider() {
|
||||
protected ReactiveDatabaseSelectionProvider reactiveDatabaseSelectionProvider() {
|
||||
|
||||
return ReactiveDatabaseSelectionProvider.getDefaultSelectionProvider();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.config;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
import org.apiguardian.api.API;
|
||||
|
||||
/**
|
||||
* An internally used CDI {@link Qualifier} to mark all beans produced by our
|
||||
* {@link Neo4jCdiConfigurationSupport configuration support} as built in.
|
||||
* When the {@link Neo4jCdiExtension Spring Data Neo4j CDI extension} is used,
|
||||
* you can opt in to override any of the following beans by providing a {@link javax.enterprise.inject.Produces @Produces} method with the
|
||||
* corresponding return type:
|
||||
* <ul>
|
||||
* <li>{@link org.springframework.data.neo4j.core.convert.Neo4jConversions}</li>
|
||||
* <li>{@link org.springframework.data.neo4j.core.DatabaseSelectionProvider}</li>
|
||||
* <li>{@link org.springframework.data.neo4j.core.Neo4jOperations}</li>*
|
||||
* </ul>
|
||||
* The order in which the types are presented reflects the usefulness over overriding such a bean.
|
||||
* You might want to add additional conversions to the mapping or provide a bean that dynamically selects a Neo4j database.
|
||||
* Running a custom bean of the template or client might prove useful if you want to add additional methods.
|
||||
*
|
||||
* @author Michael J. Simons
|
||||
* @soundtrack Buckethead - SIGIL Soundtrack
|
||||
* @since 6.0
|
||||
*/
|
||||
@API(status = API.Status.STABLE, since = "6.0")
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Qualifier
|
||||
public @interface Builtin {
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.config;
|
||||
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.enterprise.inject.Any;
|
||||
import javax.enterprise.inject.Instance;
|
||||
import javax.enterprise.inject.Produces;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apiguardian.api.API;
|
||||
import org.neo4j.driver.Driver;
|
||||
import org.springframework.data.mapping.callback.EntityCallback;
|
||||
import org.springframework.data.mapping.callback.EntityCallbacks;
|
||||
import org.springframework.data.neo4j.core.DatabaseSelectionProvider;
|
||||
import org.springframework.data.neo4j.core.Neo4jClient;
|
||||
import org.springframework.data.neo4j.core.Neo4jOperations;
|
||||
import org.springframework.data.neo4j.core.Neo4jTemplate;
|
||||
import org.springframework.data.neo4j.core.convert.Neo4jConversions;
|
||||
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
|
||||
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
|
||||
import org.springframework.data.neo4j.repository.event.BeforeBindCallback;
|
||||
import org.springframework.data.neo4j.repository.event.IdGeneratingBeforeBindCallback;
|
||||
import org.springframework.data.neo4j.repository.event.OptimisticLockingBeforeBindCallback;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* Support class that can be used as is for all necessary CDI beans or as a blueprint for custom producers.
|
||||
*
|
||||
* @author Michael J. Simons
|
||||
* @soundtrack Buckethead - SIGIL Soundtrack
|
||||
* @since 6.0
|
||||
*/
|
||||
@API(status = API.Status.INTERNAL, since = "6.0")
|
||||
@ApplicationScoped
|
||||
class Neo4jCdiConfigurationSupport {
|
||||
|
||||
private <T> T resolve(Instance<T> instance) {
|
||||
if (!instance.isAmbiguous()) {
|
||||
return instance.get();
|
||||
}
|
||||
|
||||
Instance<T> defaultInstance = instance.select(Neo4jCdiExtension.DEFAULT_BEAN);
|
||||
return defaultInstance.get();
|
||||
}
|
||||
|
||||
@Produces @Builtin @Singleton
|
||||
public Neo4jConversions neo4jConversions() {
|
||||
return new Neo4jConversions();
|
||||
}
|
||||
|
||||
@Produces @Builtin @Singleton
|
||||
public DatabaseSelectionProvider databaseSelectionProvider() {
|
||||
|
||||
return DatabaseSelectionProvider.getDefaultSelectionProvider();
|
||||
}
|
||||
|
||||
@Produces @Builtin @Singleton
|
||||
public Neo4jOperations neo4jOperations(
|
||||
final @Any Instance<Neo4jClient> neo4jClient,
|
||||
final @Any Instance<Neo4jMappingContext> mappingContext,
|
||||
final @Any Instance<DatabaseSelectionProvider> databaseNameProvider,
|
||||
final Instance<BeforeBindCallback> services
|
||||
) {
|
||||
|
||||
EntityCallbacks entityCallbacks = EntityCallbacks.create(services.stream().toArray(EntityCallback[]::new));
|
||||
return new Neo4jTemplate(resolve(neo4jClient), resolve(mappingContext), resolve(databaseNameProvider),
|
||||
entityCallbacks);
|
||||
}
|
||||
|
||||
@Produces @Singleton
|
||||
public Neo4jClient neo4jClient(Driver driver) {
|
||||
return Neo4jClient.create(driver);
|
||||
}
|
||||
|
||||
@Produces @Singleton
|
||||
public Neo4jMappingContext neo4jMappingContext(final Driver driver, final @Any Instance<Neo4jConversions> neo4JConversions) {
|
||||
|
||||
Neo4jMappingContext neo4jMappingContext = new Neo4jMappingContext(resolve(neo4JConversions), driver.defaultTypeSystem());
|
||||
return neo4jMappingContext;
|
||||
}
|
||||
|
||||
@Produces @Singleton
|
||||
public BeforeBindCallback<Object> idGeneratingBeforeBindCallback(
|
||||
final @Any Instance<Neo4jMappingContext> mappingContext) {
|
||||
|
||||
return new IdGeneratingBeforeBindCallback(resolve(mappingContext));
|
||||
}
|
||||
|
||||
@Produces @Singleton
|
||||
public BeforeBindCallback<Object> optimisticLockingBeforeBindCallback(
|
||||
final @Any Instance<Neo4jMappingContext> mappingContext) {
|
||||
|
||||
return new OptimisticLockingBeforeBindCallback(resolve(mappingContext));
|
||||
}
|
||||
|
||||
@Produces @Singleton
|
||||
public PlatformTransactionManager transactionManager(
|
||||
Driver driver, @Any Instance<DatabaseSelectionProvider> databaseNameProvider) {
|
||||
|
||||
return new Neo4jTransactionManager(driver, resolve(databaseNameProvider));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.config;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.enterprise.event.Observes;
|
||||
import javax.enterprise.inject.Any;
|
||||
import javax.enterprise.inject.Default;
|
||||
import javax.enterprise.inject.spi.AfterBeanDiscovery;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
|
||||
import javax.enterprise.util.AnnotationLiteral;
|
||||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apiguardian.api.API;
|
||||
import org.springframework.core.log.LogAccessor;
|
||||
import org.springframework.data.neo4j.repository.support.Neo4jRepositoryFactoryCdiBean;
|
||||
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
|
||||
import org.springframework.data.repository.config.CustomRepositoryImplementationDetector;
|
||||
|
||||
/**
|
||||
* This CDI extension enables Spring Data Neo4j on a CDI 2.0 compatible CDI container. It creates a Neo4j client, template
|
||||
* and brings in the Neo4j repository mechanism as well. It is the main entry point to our CDI support.
|
||||
* <p/>
|
||||
* It requires the presence of a Neo4j Driver bean. Other beans, like the {@link org.springframework.data.neo4j.core.convert.Neo4jConversions}
|
||||
* can be overwritten by providing a producer of it. If such a producer or bean is added, it must not use any {@link javax.inject.Qualifier @Qualifier}
|
||||
* on the bean.
|
||||
* <p/>
|
||||
* This CDI extension can be used either via a build in service loader mechanism or through building a context manually.
|
||||
*
|
||||
* @author Michael J. Simons
|
||||
* @soundtrack Juse Ju - Millennium
|
||||
* @since 6.0
|
||||
*/
|
||||
@API(status = API.Status.STABLE, since = "6.0")
|
||||
public final class Neo4jCdiExtension extends CdiRepositoryExtensionSupport {
|
||||
|
||||
/**
|
||||
* An annotation literal used for selecting default CDI beans.
|
||||
*/
|
||||
public static final AnnotationLiteral<Default> DEFAULT_BEAN = new AnnotationLiteral<Default>() {
|
||||
@Override public Class<? extends Annotation> annotationType() {
|
||||
return Default.class;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* An annotation literal used for selecting {@link Any @Any} annotated beans.
|
||||
*/
|
||||
public static final AnnotationLiteral<Any> ANY_BEAN = new AnnotationLiteral<Any>() {
|
||||
@Override public Class<? extends Annotation> annotationType() {
|
||||
return Any.class;
|
||||
}
|
||||
};
|
||||
|
||||
private static final LogAccessor log = new LogAccessor(LogFactory.getLog(Neo4jCdiExtension.class));
|
||||
|
||||
public Neo4jCdiExtension() {
|
||||
log.info("Activating CDI extension for Spring Data Neo4j repositories.");
|
||||
}
|
||||
|
||||
void addNeo4jBeansProducer(@Observes BeforeBeanDiscovery event) {
|
||||
event.addAnnotatedType(Neo4jCdiConfigurationSupport.class, "Neo4jCDIConfigurationSupport");
|
||||
}
|
||||
|
||||
void registerRepositoryFactoryBeanPerRepositoryType(@Observes AfterBeanDiscovery event, BeanManager beanManager) {
|
||||
|
||||
Optional<CustomRepositoryImplementationDetector> optionalCustomRepositoryImplementationDetector =
|
||||
Optional.ofNullable(getCustomImplementationDetector());
|
||||
|
||||
for (Map.Entry<Class<?>, Set<Annotation>> entry : getRepositoryTypes()) {
|
||||
|
||||
Class<?> repositoryType = entry.getKey();
|
||||
Set<Annotation> qualifiers = entry.getValue();
|
||||
|
||||
Neo4jRepositoryFactoryCdiBean<?> repositoryBean = new Neo4jRepositoryFactoryCdiBean<>(
|
||||
qualifiers,
|
||||
repositoryType,
|
||||
beanManager,
|
||||
optionalCustomRepositoryImplementationDetector
|
||||
);
|
||||
|
||||
registerBean(repositoryBean);
|
||||
event.addBean(repositoryBean);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,12 @@ public final class Neo4jTemplate implements Neo4jOperations, BeanFactoryAware {
|
||||
public Neo4jTemplate(Neo4jClient neo4jClient, Neo4jMappingContext neo4jMappingContext,
|
||||
DatabaseSelectionProvider databaseSelectionProvider) {
|
||||
|
||||
this(neo4jClient, neo4jMappingContext, databaseSelectionProvider, EntityCallbacks.create());
|
||||
}
|
||||
|
||||
public Neo4jTemplate(Neo4jClient neo4jClient, Neo4jMappingContext neo4jMappingContext,
|
||||
DatabaseSelectionProvider databaseSelectionProvider, EntityCallbacks entityCallbacks) {
|
||||
|
||||
Assert.notNull(neo4jClient, "The Neo4jClient is required");
|
||||
Assert.notNull(neo4jMappingContext, "The Neo4jMappingContext is required");
|
||||
Assert.notNull(databaseSelectionProvider, "The database name provider is required");
|
||||
@@ -100,7 +106,7 @@ public final class Neo4jTemplate implements Neo4jOperations, BeanFactoryAware {
|
||||
this.neo4jClient = neo4jClient;
|
||||
this.neo4jMappingContext = neo4jMappingContext;
|
||||
this.cypherGenerator = CypherGenerator.INSTANCE;
|
||||
this.eventSupport = new Neo4jEvents(EntityCallbacks.create());
|
||||
this.eventSupport = new Neo4jEvents(entityCallbacks);
|
||||
|
||||
this.databaseSelectionProvider = databaseSelectionProvider;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apiguardian.api.API;
|
||||
import org.neo4j.driver.Driver;
|
||||
import org.neo4j.driver.types.TypeSystem;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
@@ -82,9 +83,27 @@ public final class Neo4jMappingContext extends AbstractMappingContext<Neo4jPersi
|
||||
|
||||
public Neo4jMappingContext(Neo4jConversions neo4jConversions) {
|
||||
|
||||
this(neo4jConversions, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This API is primarly used from inside the CDI extension to configure the type system. This is necessary as
|
||||
* we don't get notified of the context via {@link #setApplicationContext(ApplicationContext applicationContext)}.
|
||||
*
|
||||
* @param neo4jConversions The conversions to be used
|
||||
* @param typeSystem The current drivers typeystem
|
||||
*/
|
||||
@API(status = API.Status.INTERNAL, since = "6.0")
|
||||
public Neo4jMappingContext(Neo4jConversions neo4jConversions, TypeSystem typeSystem) {
|
||||
|
||||
super.setSimpleTypeHolder(Neo4jSimpleTypes.HOLDER);
|
||||
this.neo4jConversions = neo4jConversions;
|
||||
this.converter = new DefaultNeo4jConverter(neo4jConversions, nodeDescriptionStore);
|
||||
|
||||
DefaultNeo4jConverter defaultNeo4jConverter = new DefaultNeo4jConverter(neo4jConversions, nodeDescriptionStore);
|
||||
if (typeSystem != null) {
|
||||
defaultNeo4jConverter.setTypeSystem(typeSystem);
|
||||
}
|
||||
this.converter = defaultNeo4jConverter;
|
||||
}
|
||||
|
||||
public Neo4jConverter getConverter() {
|
||||
|
||||
@@ -37,7 +37,6 @@ public final class IdGeneratingBeforeBindCallback implements BeforeBindCallback<
|
||||
|
||||
@Override
|
||||
public Object onBeforeBind(Object entity) {
|
||||
|
||||
return idPopulator.populateIfNecessary(entity);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.repository.support;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.enterprise.context.spi.CreationalContext;
|
||||
import javax.enterprise.inject.spi.Bean;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
|
||||
import org.apiguardian.api.API;
|
||||
import org.springframework.data.neo4j.config.Neo4jCdiExtension;
|
||||
import org.springframework.data.neo4j.core.Neo4jOperations;
|
||||
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
|
||||
import org.springframework.data.repository.cdi.CdiRepositoryBean;
|
||||
import org.springframework.data.repository.config.CustomRepositoryImplementationDetector;
|
||||
|
||||
/**
|
||||
* The CDI pendant to the {@link Neo4jRepositoryFactoryBean}. It creates instances of {@link Neo4jRepositoryFactory}.
|
||||
*
|
||||
* @param <T> The type of the repository being created
|
||||
* @author Michael J. Simons
|
||||
* @soundtrack Various - TRON Legacy R3conf1gur3d
|
||||
* @since 6.0
|
||||
*/
|
||||
@API(status = API.Status.INTERNAL, since = "6.0")
|
||||
public final class Neo4jRepositoryFactoryCdiBean<T> extends CdiRepositoryBean<T> {
|
||||
|
||||
private final BeanManager beanManager;
|
||||
|
||||
public Neo4jRepositoryFactoryCdiBean(Set<Annotation> qualifiers, Class<T> repositoryType,
|
||||
BeanManager beanManager, Optional<CustomRepositoryImplementationDetector> detector) {
|
||||
super(qualifiers, repositoryType, beanManager, detector);
|
||||
|
||||
this.beanManager = beanManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType) {
|
||||
|
||||
Neo4jOperations neo4jOperations = getReference(Neo4jOperations.class, creationalContext);
|
||||
Neo4jMappingContext mappingContext = getReference(Neo4jMappingContext.class, creationalContext);
|
||||
|
||||
return create(() -> new Neo4jRepositoryFactory(neo4jOperations, mappingContext), repositoryType);
|
||||
}
|
||||
|
||||
private <T> T getReference(Class<T> clazz, CreationalContext<?> creationalContext) {
|
||||
|
||||
Set<Bean<?>> beans = beanManager.getBeans(clazz, Neo4jCdiExtension.ANY_BEAN);
|
||||
if (beans.size() > 1) {
|
||||
beans = beans.stream()
|
||||
.filter(b -> b.getQualifiers().contains(Neo4jCdiExtension.DEFAULT_BEAN))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
Bean<?> bean = beanManager.resolve(beans);
|
||||
return (T) beanManager.getReference(bean, clazz, creationalContext);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
org.springframework.data.neo4j.config.Neo4jCdiExtension
|
||||
@@ -54,14 +54,6 @@ class User {
|
||||
}
|
||||
}
|
||||
|
||||
// tag::faq.multidatabase[]
|
||||
// end::faq.multidatabase[]
|
||||
// tag::faq.multidatabase[]
|
||||
// end::faq.multidatabase[]
|
||||
// tag::faq.multidatabase[]
|
||||
|
||||
// end::faq.multidatabase[]
|
||||
|
||||
/**
|
||||
* @author Michael J. Simons
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.integration.cdi;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.neo4j.driver.Driver;
|
||||
|
||||
/**
|
||||
* @author Michael J. Simons
|
||||
* @soundtrack Various - TRON Legacy R3conf1gur3d
|
||||
*/
|
||||
class Neo4jBasedService {
|
||||
|
||||
final Driver driver;
|
||||
|
||||
final PersonRepository personRepository;
|
||||
|
||||
@Inject
|
||||
Neo4jBasedService(Driver driver, PersonRepository personRepository) {
|
||||
this.driver = driver;
|
||||
this.personRepository = personRepository;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.integration.cdi;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.enterprise.inject.AmbiguousResolutionException;
|
||||
import javax.enterprise.inject.Produces;
|
||||
import javax.enterprise.inject.se.SeContainer;
|
||||
import javax.enterprise.inject.se.SeContainerInitializer;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.neo4j.driver.Driver;
|
||||
import org.springframework.data.neo4j.config.Neo4jCdiExtension;
|
||||
import org.springframework.data.neo4j.core.DatabaseSelectionProvider;
|
||||
import org.springframework.data.neo4j.core.Neo4jOperations;
|
||||
import org.springframework.data.neo4j.core.convert.Neo4jConversions;
|
||||
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
|
||||
import org.springframework.data.neo4j.test.Neo4jExtension;
|
||||
|
||||
/**
|
||||
* @author Michael J. Simons
|
||||
* @soundtrack Various - TRON Legacy R3conf1gur3d
|
||||
*/
|
||||
@ExtendWith(Neo4jExtension.class)
|
||||
class Neo4jCdiExtensionIT {
|
||||
|
||||
protected static Neo4jExtension.Neo4jConnectionSupport connectionSupport;
|
||||
|
||||
@ApplicationScoped
|
||||
static class RealDriverFactory {
|
||||
|
||||
@Produces
|
||||
@Singleton
|
||||
public Driver driver() {
|
||||
return connectionSupport.getDriver();
|
||||
}
|
||||
}
|
||||
|
||||
@ApplicationScoped
|
||||
static class MockedDriverFactory {
|
||||
|
||||
@Produces
|
||||
@Singleton
|
||||
public Driver driver() {
|
||||
return Mockito.mock(Driver.class);
|
||||
}
|
||||
}
|
||||
|
||||
@ApplicationScoped
|
||||
static class CustomDependencyProducer {
|
||||
|
||||
Neo4jConversions conversions = Mockito.mock(Neo4jConversions.class);
|
||||
|
||||
DatabaseSelectionProvider databaseSelectionProvider = Mockito.mock(DatabaseSelectionProvider.class);
|
||||
|
||||
Neo4jOperations neo4jOperations = Mockito.mock(Neo4jOperations.class);
|
||||
|
||||
@Produces @Singleton
|
||||
public Neo4jConversions getConversions() {
|
||||
return conversions;
|
||||
}
|
||||
|
||||
@Produces @Singleton
|
||||
public DatabaseSelectionProvider getDatabaseSelectionProvider() {
|
||||
return databaseSelectionProvider;
|
||||
}
|
||||
|
||||
@Produces @Singleton
|
||||
public Neo4jOperations getNeo4jOperations() {
|
||||
return neo4jOperations;
|
||||
}
|
||||
}
|
||||
|
||||
@ApplicationScoped
|
||||
static class BrokenCustomDependencyProducer {
|
||||
|
||||
@Produces @Singleton
|
||||
public Neo4jConversions getConversions1() {
|
||||
return Mockito.mock(Neo4jConversions.class);
|
||||
}
|
||||
|
||||
@Produces @Singleton
|
||||
public Neo4jConversions getConversions2() {
|
||||
return Mockito.mock(Neo4jConversions.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void cdiExtensionShouldProduceFunctionalRepositories() {
|
||||
|
||||
try (SeContainer container = SeContainerInitializer.newInstance()
|
||||
.disableDiscovery()
|
||||
.addExtensions(Neo4jCdiExtension.class)
|
||||
.addBeanClasses(RealDriverFactory.class, PersonRepository.class, Neo4jBasedService.class)
|
||||
.initialize()) {
|
||||
Neo4jBasedService client = container
|
||||
.select(Neo4jBasedService.class).get();
|
||||
|
||||
assertThat(client).isNotNull();
|
||||
assertThat(client.driver).isNotNull();
|
||||
assertThat(client.personRepository).isNotNull();
|
||||
|
||||
Person p = client.personRepository.save(new Person("Hello"));
|
||||
assertThat(p.getId()).isNotNull();
|
||||
|
||||
Optional<Person> loadedPerson = client.personRepository.findById(p.getId());
|
||||
assertThat(loadedPerson).isPresent().hasValueSatisfying(v -> v.getId().equals(p.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAllowToOverrideASetOfDependents() {
|
||||
|
||||
Class<?> configurationSupport = getNeo4jCdiConfigurationSupport();
|
||||
try (SeContainer container = SeContainerInitializer.newInstance()
|
||||
.disableDiscovery()
|
||||
.addBeanClasses(
|
||||
MockedDriverFactory.class,
|
||||
CustomDependencyProducer.class,
|
||||
configurationSupport
|
||||
)
|
||||
.initialize()) {
|
||||
|
||||
CustomDependencyProducer customDependencyProducer = container.select(CustomDependencyProducer.class).get();
|
||||
|
||||
assertThat(container.select(Neo4jConversions.class).get())
|
||||
.isEqualTo(customDependencyProducer.getConversions());
|
||||
assertThat(container.select(DatabaseSelectionProvider.class).get())
|
||||
.isEqualTo(customDependencyProducer.getDatabaseSelectionProvider());
|
||||
assertThat(container.select(Neo4jOperations.class).get())
|
||||
.isEqualTo(customDependencyProducer.getNeo4jOperations());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRequireUniqueDefaultBeans() {
|
||||
|
||||
Class<?> configurationSupport = getNeo4jCdiConfigurationSupport();
|
||||
try (SeContainer container = SeContainerInitializer.newInstance()
|
||||
.disableDiscovery()
|
||||
.addBeanClasses(
|
||||
MockedDriverFactory.class,
|
||||
BrokenCustomDependencyProducer.class,
|
||||
configurationSupport
|
||||
)
|
||||
.initialize()) {
|
||||
|
||||
assertThatExceptionOfType(AmbiguousResolutionException.class).isThrownBy(() -> {
|
||||
Neo4jMappingContext context = container.select(Neo4jMappingContext.class).get();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> getNeo4jCdiConfigurationSupport() {
|
||||
try {
|
||||
// Wrapped in a reflection call so that we don't need to make it public just
|
||||
// for testing it's producer methods.
|
||||
return Class.forName("org.springframework.data.neo4j.config.Neo4jCdiConfigurationSupport");
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("¯\\_(ツ)_/¯", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.integration.cdi;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.neo4j.core.schema.GeneratedValue;
|
||||
import org.springframework.data.neo4j.core.schema.Id;
|
||||
import org.springframework.data.neo4j.core.schema.Node;
|
||||
|
||||
/**
|
||||
* This domain object features a client side generated ID on purpose. It is needed to verify that the callbacks generating
|
||||
* those are actually registered correct.
|
||||
*
|
||||
* @author Michael J. Simons
|
||||
* @soundtrack Various - TRON Legacy R3conf1gur3d
|
||||
*/
|
||||
@Node
|
||||
class Person {
|
||||
|
||||
@Id @GeneratedValue
|
||||
private UUID id;
|
||||
|
||||
@CreatedDate
|
||||
private LocalDate createdAt;
|
||||
|
||||
private final String name;
|
||||
|
||||
Person(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public LocalDate getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2011-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.integration.cdi;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.data.neo4j.repository.Neo4jRepository;
|
||||
|
||||
/**
|
||||
* @author Michael J. Simons
|
||||
* @soundtrack Various - TRON Legacy R3conf1gur3d
|
||||
*/
|
||||
interface PersonRepository extends Neo4jRepository<Person, UUID> {
|
||||
}
|
||||
@@ -41,7 +41,7 @@ class RepositoryWithADifferentDatabaseIT extends RepositoryIT {
|
||||
@BeforeAll
|
||||
static void createTestDatabase() {
|
||||
|
||||
try (Session session = neo4jConnectionSupport.driverInstance.session(SessionConfig.forDatabase("system"))) {
|
||||
try (Session session = neo4jConnectionSupport.getDriver().session(SessionConfig.forDatabase("system"))) {
|
||||
|
||||
session.run("CREATE DATABASE " + TEST_DATABASE_NAME).consume();
|
||||
}
|
||||
@@ -50,7 +50,7 @@ class RepositoryWithADifferentDatabaseIT extends RepositoryIT {
|
||||
@AfterAll
|
||||
static void dropTestDatabase() {
|
||||
|
||||
try (Session session = neo4jConnectionSupport.driverInstance.session(SessionConfig.forDatabase("system"))) {
|
||||
try (Session session = neo4jConnectionSupport.getDriver().session(SessionConfig.forDatabase("system"))) {
|
||||
|
||||
session.run("DROP DATABASE " + TEST_DATABASE_NAME).consume();
|
||||
}
|
||||
|
||||
@@ -2220,7 +2220,7 @@ class ReactiveRepositoryIT {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
protected ReactiveDatabaseSelectionProvider reactiveNeo4jDatabaseNameProvider() {
|
||||
protected ReactiveDatabaseSelectionProvider reactiveDatabaseSelectionProvider() {
|
||||
return Optional.ofNullable(databaseSelection.getValue())
|
||||
.map(ReactiveDatabaseSelectionProvider::createStaticDatabaseSelectionProvider)
|
||||
.orElse(ReactiveDatabaseSelectionProvider.getDefaultSelectionProvider());
|
||||
|
||||
@@ -41,7 +41,7 @@ class ReactiveRepositoryWithADifferentDatabaseIT extends ReactiveRepositoryIT {
|
||||
@BeforeAll
|
||||
static void createTestDatabase() {
|
||||
|
||||
try (Session session = neo4jConnectionSupport.driverInstance.session(SessionConfig.forDatabase("system"))) {
|
||||
try (Session session = neo4jConnectionSupport.getDriver().session(SessionConfig.forDatabase("system"))) {
|
||||
|
||||
session.run("CREATE DATABASE " + TEST_DATABASE_NAME).consume();
|
||||
}
|
||||
@@ -50,7 +50,7 @@ class ReactiveRepositoryWithADifferentDatabaseIT extends ReactiveRepositoryIT {
|
||||
@AfterAll
|
||||
static void dropTestDatabase() {
|
||||
|
||||
try (Session session = neo4jConnectionSupport.driverInstance.session(SessionConfig.forDatabase("system"))) {
|
||||
try (Session session = neo4jConnectionSupport.getDriver().session(SessionConfig.forDatabase("system"))) {
|
||||
|
||||
session.run("DROP DATABASE " + TEST_DATABASE_NAME).consume();
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ public class Neo4jExtension implements BeforeAllCallback, BeforeEachCallback {
|
||||
/**
|
||||
* Shared instance of the standard (non-routing) driver.
|
||||
*/
|
||||
public volatile Driver driverInstance;
|
||||
private volatile Driver driverInstance;
|
||||
|
||||
public Neo4jConnectionSupport(String url, AuthToken authToken) {
|
||||
this.url = url;
|
||||
|
||||
Reference in New Issue
Block a user