Merge pull request #5458 from jexp/contrib
* pr/5458: Polish contribution Add Neo4j support
This commit is contained in:
commit
aa171d1945
|
@ -166,6 +166,11 @@
|
|||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-redis</artifactId>
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDa
|
|||
import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.test.util.ApplicationContextTestUtils;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
@ -63,6 +64,7 @@ public class SpringApplicationHierarchyTests {
|
|||
@EnableAutoConfiguration(exclude = { ElasticsearchDataAutoConfiguration.class,
|
||||
ElasticsearchRepositoriesAutoConfiguration.class,
|
||||
CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
|
||||
Neo4jAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class,
|
||||
RedisRepositoriesAutoConfiguration.class }, excludeName = {
|
||||
"org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" })
|
||||
|
@ -75,6 +77,7 @@ public class SpringApplicationHierarchyTests {
|
|||
ElasticsearchDataAutoConfiguration.class,
|
||||
ElasticsearchRepositoriesAutoConfiguration.class,
|
||||
CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
|
||||
Neo4jAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class,
|
||||
RedisRepositoriesAutoConfiguration.class }, excludeName = {
|
||||
"org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" })
|
||||
|
|
|
@ -379,6 +379,17 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j</artifactId>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<groupId>org.slf4j</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-redis</artifactId>
|
||||
|
@ -635,5 +646,6 @@
|
|||
<artifactId>tomcat-embed-jasper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.neo4j;
|
||||
|
||||
import org.neo4j.ogm.session.Neo4jSession;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
|
||||
import org.springframework.data.neo4j.repository.config.Neo4jRepositoryConfigurationExtension;
|
||||
import org.springframework.data.neo4j.repository.support.GraphRepositoryFactoryBean;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Neo4j
|
||||
* Repositories.
|
||||
* <p>
|
||||
* Activates when there is no bean of type
|
||||
* {@link org.springframework.data.neo4j.repository.support.GraphRepositoryFactoryBean}
|
||||
* configured in the context, the Spring Data Neo4j
|
||||
* {@link org.springframework.data.neo4j.repository.GraphRepository} type is on the
|
||||
* classpath, the Neo4j client driver API is on the classpath, and there is no other
|
||||
* configured {@link org.springframework.data.neo4j.repository.GraphRepository}.
|
||||
* <p>
|
||||
* Once in effect, the auto-configuration is the equivalent of enabling Neo4j repositories
|
||||
* using the
|
||||
* {@link org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories}
|
||||
* annotation.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Oliver Gierke
|
||||
* @author Josh Long
|
||||
* @since 1.4.0
|
||||
* @see EnableNeo4jRepositories
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ Neo4jSession.class, GraphRepository.class })
|
||||
@ConditionalOnMissingBean({ GraphRepositoryFactoryBean.class, Neo4jRepositoryConfigurationExtension.class })
|
||||
@ConditionalOnProperty(prefix = "spring.data.neo4j.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||
@Import(Neo4jRepositoriesAutoConfigureRegistrar.class)
|
||||
@AutoConfigureAfter(Neo4jAutoConfiguration.class)
|
||||
public class Neo4jRepositoriesAutoConfiguration {
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.neo4j;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
|
||||
import org.springframework.data.neo4j.repository.config.Neo4jRepositoryConfigurationExtension;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
|
||||
/**
|
||||
* {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Neo4j
|
||||
* Repositories.
|
||||
*
|
||||
* @author Michael Hunger
|
||||
*/
|
||||
class Neo4jRepositoriesAutoConfigureRegistrar extends
|
||||
AbstractRepositoryConfigurationSourceSupport {
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotation() {
|
||||
return EnableNeo4jRepositories.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getConfiguration() {
|
||||
return EnableNeo4jRepositoriesConfiguration.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() {
|
||||
return new Neo4jRepositoryConfigurationExtension();
|
||||
}
|
||||
|
||||
@EnableNeo4jRepositories
|
||||
private static class EnableNeo4jRepositoriesConfiguration {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright 2012-2015 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auto-configuration for Spring Data Neo4j.
|
||||
*/
|
||||
package org.springframework.boot.autoconfigure.data.neo4j;
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.neo4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.neo4j.ogm.session.Neo4jSession;
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.neo4j.ogm.session.SessionFactory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.neo4j.SessionFactoryProvider;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.data.neo4j.config.Neo4jConfiguration;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
import org.springframework.data.neo4j.template.Neo4jTemplate;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Neo4j support.
|
||||
* <p>
|
||||
* Registers a {@link Neo4jTemplate} bean if no other bean of
|
||||
* the same type is configured.
|
||||
*
|
||||
* @author Michael Hunger
|
||||
* @author Josh Long
|
||||
* @author Vince Bickers
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.4.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({Neo4jSession.class, Neo4jOperations.class})
|
||||
@ConditionalOnMissingBean(Neo4jOperations.class)
|
||||
@EnableConfigurationProperties(Neo4jProperties.class)
|
||||
public class Neo4jAutoConfiguration {
|
||||
|
||||
@Configuration
|
||||
@Import(SessionFactoryProviderConfiguration.class)
|
||||
public static class SpringBootNeo4jConfiguration extends Neo4jConfiguration {
|
||||
|
||||
private final ObjectProvider<SessionFactoryProvider> sessionFactoryProvider;
|
||||
|
||||
public SpringBootNeo4jConfiguration(ObjectProvider<SessionFactoryProvider> sessionFactoryProvider) {
|
||||
this.sessionFactoryProvider = sessionFactoryProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionFactory getSessionFactory() {
|
||||
SessionFactoryProvider provider = this.sessionFactoryProvider.getObject();
|
||||
return provider.getSessionFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Scope(scopeName = "${spring.data.neo4j.session.scope:singleton}",
|
||||
proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||
@Override
|
||||
public Session getSession() throws Exception {
|
||||
return getSessionFactory().openSession();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(Neo4jConfigurationConfiguration.class)
|
||||
static class SessionFactoryProviderConfiguration implements BeanFactoryAware {
|
||||
|
||||
private final org.neo4j.ogm.config.Configuration configuration;
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
SessionFactoryProviderConfiguration(org.neo4j.ogm.config.Configuration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public SessionFactoryProvider sessionFactoryProvider() {
|
||||
SessionFactoryProvider provider = new SessionFactoryProvider();
|
||||
provider.setConfiguration(this.configuration);
|
||||
provider.setPackagesToScan(getPackagesToScan());
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
||||
}
|
||||
|
||||
protected String[] getPackagesToScan() {
|
||||
if (AutoConfigurationPackages.has(this.beanFactory)) {
|
||||
List<String> basePackages = AutoConfigurationPackages.get(this.beanFactory);
|
||||
return basePackages.toArray(new String[basePackages.size()]);
|
||||
}
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Neo4jConfigurationConfiguration {
|
||||
|
||||
private final Neo4jProperties properties;
|
||||
|
||||
Neo4jConfigurationConfiguration(Neo4jProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public org.neo4j.ogm.config.Configuration configuration() {
|
||||
return this.properties.createConfiguration();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.neo4j;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import org.neo4j.ogm.config.Configuration;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Configuration properties for Neo4j.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Michael Hunger
|
||||
* @author Vince Bickers
|
||||
* @since 1.4.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "spring.data.neo4j")
|
||||
public class Neo4jProperties implements ApplicationContextAware {
|
||||
|
||||
static final String EMBEDDED_DRIVER = "org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver";
|
||||
|
||||
static final String HTTP_DRIVER = "org.neo4j.ogm.drivers.http.driver.HttpDriver";
|
||||
|
||||
static final String DEFAULT_HTTP_URI = "http://localhost:7474";
|
||||
|
||||
/**
|
||||
* URI used by the driver. Auto-detected by default.
|
||||
*/
|
||||
private String uri;
|
||||
|
||||
/**
|
||||
* Login user of the server.
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* Login password of the server.
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Compiler to use.
|
||||
*/
|
||||
private String compiler;
|
||||
|
||||
private final Embedded embedded = new Embedded();
|
||||
|
||||
private ClassLoader classLoader = Neo4jProperties.class.getClassLoader();
|
||||
|
||||
public String getUri() {
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getCompiler() {
|
||||
return this.compiler;
|
||||
}
|
||||
|
||||
public void setCompiler(String compiler) {
|
||||
this.compiler = compiler;
|
||||
}
|
||||
|
||||
public Embedded getEmbedded() {
|
||||
return this.embedded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
|
||||
this.classLoader = ctx.getClassLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link Configuration} based on the state of this instance.
|
||||
* @return a configuration
|
||||
*/
|
||||
public Configuration createConfiguration() {
|
||||
Configuration configuration = new Configuration();
|
||||
if (this.uri == null) {
|
||||
if (getEmbedded().isEnabled()
|
||||
&& ClassUtils.isPresent(EMBEDDED_DRIVER, this.classLoader)) {
|
||||
configuration.driverConfiguration().setDriverClassName(EMBEDDED_DRIVER);
|
||||
}
|
||||
else {
|
||||
configuration.driverConfiguration().setDriverClassName(HTTP_DRIVER);
|
||||
configuration.driverConfiguration().setURI(DEFAULT_HTTP_URI);
|
||||
}
|
||||
}
|
||||
else {
|
||||
configuration.driverConfiguration().setDriverClassName(deduceDriverFromUri());
|
||||
configuration.driverConfiguration().setURI(this.uri);
|
||||
}
|
||||
|
||||
if (this.username != null && this.password != null) {
|
||||
configuration.driverConfiguration().setCredentials(this.username, this.password);
|
||||
}
|
||||
if (this.compiler != null) {
|
||||
configuration.compilerConfiguration().setCompilerClassName(this.compiler);
|
||||
}
|
||||
return configuration;
|
||||
}
|
||||
|
||||
private String deduceDriverFromUri() {
|
||||
try {
|
||||
URI uri = new URI(this.uri);
|
||||
String scheme = uri.getScheme();
|
||||
if (scheme == null || scheme.equals("file")) {
|
||||
return EMBEDDED_DRIVER;
|
||||
}
|
||||
else if ("http".equals(scheme)) {
|
||||
return HTTP_DRIVER;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Could not deduce driver to use based on URI '" + uri + "'");
|
||||
}
|
||||
}
|
||||
catch (URISyntaxException ex) {
|
||||
throw new IllegalArgumentException("Invalid URI for spring.data.neo4j.uri '" + this.uri + "'", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Embedded {
|
||||
|
||||
/**
|
||||
* Enable embedded mode if the embedded driver is available.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Auto-configuration for Neo4j.
|
||||
*/
|
||||
package org.springframework.boot.autoconfigure.neo4j;
|
|
@ -90,6 +90,18 @@
|
|||
"description": "Enable Mongo repositories.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "spring.data.neo4j.repositories.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Enable Neo4j repositories.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "spring.data.neo4j.session.scope",
|
||||
"type": "java.lang.String",
|
||||
"description": "Scope (lifetime) of the session.",
|
||||
"defaultValue": "singleton"
|
||||
},
|
||||
{
|
||||
"name": "spring.data.redis.repositories.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
|
@ -330,6 +342,36 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "spring.data.neo4j.compiler",
|
||||
"providers": [
|
||||
{
|
||||
"name": "class-reference",
|
||||
"parameters": {
|
||||
"target": "org.neo4j.ogm.compiler.Compiler"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "spring.data.neo4j.session.scope",
|
||||
"values": [
|
||||
{
|
||||
"value": "singleton"
|
||||
},
|
||||
{
|
||||
"value": "session"
|
||||
},
|
||||
{
|
||||
"value": "request"
|
||||
}
|
||||
],
|
||||
"providers": [
|
||||
{
|
||||
"name": "any"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "spring.datasource.driver-class-name",
|
||||
"providers": [
|
||||
|
|
|
@ -31,6 +31,7 @@ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositor
|
|||
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
|
||||
|
@ -68,6 +69,7 @@ org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
|
|||
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.alt.neo4j;
|
||||
|
||||
import org.springframework.boot.autoconfigure.data.neo4j.city.City;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
|
||||
public interface CityNeo4jRepository extends GraphRepository<City> {
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.neo4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
|
||||
import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.jpa.city.City;
|
||||
import org.springframework.boot.autoconfigure.data.jpa.city.CityRepository;
|
||||
import org.springframework.boot.autoconfigure.data.neo4j.country.Country;
|
||||
import org.springframework.boot.autoconfigure.data.neo4j.country.CountryRepository;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfigurationTests;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||
import org.springframework.boot.orm.jpa.EntityScan;
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.ImportSelector;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link Neo4jRepositoriesAutoConfiguration}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Oliver Gierke
|
||||
* @author Michael Hunger
|
||||
* @author Vince Bickers
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class MixedNeo4jRepositoriesAutoConfigurationTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context =
|
||||
new AnnotationConfigApplicationContext();
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
this.context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultRepositoryConfiguration() throws Exception {
|
||||
EnvironmentTestUtils.addEnvironment(this.context, "spring.datasource.initialize:false");
|
||||
this.context.register(TestConfiguration.class, BaseConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBean(CountryRepository.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMixedRepositoryConfiguration() throws Exception {
|
||||
EnvironmentTestUtils.addEnvironment(this.context, "spring.datasource.initialize:false");
|
||||
this.context.register(MixedConfiguration.class, BaseConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBean(CountryRepository.class)).isNotNull();
|
||||
assertThat(this.context.getBean(CityRepository.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJpaRepositoryConfigurationWithNeo4jTemplate() throws Exception {
|
||||
EnvironmentTestUtils.addEnvironment(this.context, "spring.datasource.initialize:false");
|
||||
this.context.register(JpaConfiguration.class, BaseConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBean(CityRepository.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testJpaRepositoryConfigurationWithNeo4jOverlap() throws Exception {
|
||||
EnvironmentTestUtils.addEnvironment(this.context, "spring.datasource.initialize:false");
|
||||
this.context.register(OverlapConfiguration.class, BaseConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBean(CityRepository.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJpaRepositoryConfigurationWithNeo4jOverlapDisabled() throws Exception {
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"spring.datasource.initialize:false",
|
||||
"spring.data.neo4j.repositories.enabled:false");
|
||||
this.context.register(OverlapConfiguration.class, BaseConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBean(CityRepository.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@TestAutoConfigurationPackage(Neo4jAutoConfigurationTests.class)
|
||||
// Not this package or its parent
|
||||
@EnableNeo4jRepositories(basePackageClasses = Country.class)
|
||||
protected static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@TestAutoConfigurationPackage(Neo4jAutoConfigurationTests.class)
|
||||
@EnableNeo4jRepositories(basePackageClasses = Country.class)
|
||||
@EntityScan(basePackageClasses = City.class)
|
||||
@EnableJpaRepositories(basePackageClasses = CityRepository.class)
|
||||
protected static class MixedConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@TestAutoConfigurationPackage(Neo4jAutoConfigurationTests.class)
|
||||
@EntityScan(basePackageClasses = City.class)
|
||||
@EnableJpaRepositories(basePackageClasses = CityRepository.class)
|
||||
protected static class JpaConfiguration {
|
||||
|
||||
}
|
||||
|
||||
// In this one the Jpa repositories and the auto-configuration packages overlap, so
|
||||
// Neo4j will try and configure the same repositories
|
||||
@Configuration
|
||||
@TestAutoConfigurationPackage(CityRepository.class)
|
||||
@EnableJpaRepositories(basePackageClasses = CityRepository.class)
|
||||
protected static class OverlapConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(Registrar.class)
|
||||
protected static class BaseConfiguration {
|
||||
|
||||
}
|
||||
|
||||
protected static class Registrar implements ImportSelector {
|
||||
|
||||
@Override
|
||||
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
|
||||
List<String> names = new ArrayList<String>();
|
||||
for (Class<?> type : new Class<?>[] {DataSourceAutoConfiguration.class,
|
||||
HibernateJpaAutoConfiguration.class,
|
||||
JpaRepositoriesAutoConfiguration.class,
|
||||
Neo4jAutoConfiguration.class,
|
||||
Neo4jRepositoriesAutoConfiguration.class}) {
|
||||
names.add(type.getName());
|
||||
}
|
||||
return names.toArray(new String[names.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.neo4j;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
|
||||
import org.springframework.boot.autoconfigure.data.neo4j.city.City;
|
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
|
||||
|
||||
/**
|
||||
* Tests for {@link Neo4jAutoConfiguration}.
|
||||
*
|
||||
* @author Josh Long
|
||||
* @author Oliver Gierke
|
||||
* @author Vince Bickers
|
||||
*/
|
||||
public class Neo4jDataAutoConfigurationTests {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
this.context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usesAutoConfigurationPackageToPickUpDomainTypes() {
|
||||
String cityPackage = City.class.getPackage().getName();
|
||||
AutoConfigurationPackages.register(this.context, cityPackage);
|
||||
this.context.register(Neo4jAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertDomainTypesDiscovered(this.context.getBean(Neo4jMappingContext.class),
|
||||
City.class);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private static void assertDomainTypesDiscovered(Neo4jMappingContext mappingContext,
|
||||
Class<?>... types) {
|
||||
for (Class<?> type : types) {
|
||||
Assertions.assertThat(mappingContext.getPersistentEntity(type)).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.neo4j;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.neo4j.ogm.session.SessionFactory;
|
||||
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
|
||||
import org.springframework.boot.autoconfigure.data.alt.neo4j.CityNeo4jRepository;
|
||||
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
|
||||
import org.springframework.boot.autoconfigure.data.neo4j.city.City;
|
||||
import org.springframework.boot.autoconfigure.data.neo4j.city.CityRepository;
|
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration;
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
|
||||
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link Neo4jRepositoriesAutoConfiguration}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Oliver Gierke
|
||||
* @author Michael Hunger
|
||||
* @author Vince Bickers
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class Neo4jRepositoriesAutoConfigurationTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
this.context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultRepositoryConfiguration() throws Exception {
|
||||
prepareApplicationContext(TestConfiguration.class);
|
||||
|
||||
assertThat(this.context.getBean(CityRepository.class)).isNotNull();
|
||||
Neo4jMappingContext mappingContext = this.context.getBean(Neo4jMappingContext.class);
|
||||
assertThat(mappingContext.getPersistentEntity(City.class)).isNotNull();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoRepositoryConfiguration() throws Exception {
|
||||
prepareApplicationContext(EmptyConfiguration.class);
|
||||
|
||||
assertThat(this.context.getBean(SessionFactory.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
|
||||
prepareApplicationContext(CustomizedConfiguration.class);
|
||||
|
||||
assertThat(this.context.getBean(CityNeo4jRepository.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test(expected = NoSuchBeanDefinitionException.class)
|
||||
public void autoConfigurationShouldNotKickInEvenIfManualConfigDidNotCreateAnyRepositories() {
|
||||
prepareApplicationContext(SortOfInvalidCustomConfiguration.class);
|
||||
|
||||
this.context.getBean(CityRepository.class);
|
||||
}
|
||||
|
||||
private void prepareApplicationContext(Class<?>... configurationClasses) {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"spring.data.neo4j.uri=http://localhost:9797");
|
||||
this.context.register(configurationClasses);
|
||||
this.context.register(Neo4jAutoConfiguration.class,
|
||||
Neo4jRepositoriesAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@TestAutoConfigurationPackage(City.class)
|
||||
protected static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@TestAutoConfigurationPackage(EmptyDataPackage.class)
|
||||
protected static class EmptyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@TestAutoConfigurationPackage(Neo4jRepositoriesAutoConfigurationTests.class)
|
||||
@EnableNeo4jRepositories(basePackageClasses = CityNeo4jRepository.class)
|
||||
protected static class CustomizedConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
// To not find any repositories
|
||||
@EnableNeo4jRepositories("foo.bar")
|
||||
@TestAutoConfigurationPackage(Neo4jRepositoriesAutoConfigurationTests.class)
|
||||
protected static class SortOfInvalidCustomConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.neo4j.city;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.neo4j.ogm.annotation.GraphId;
|
||||
import org.neo4j.ogm.annotation.NodeEntity;
|
||||
|
||||
import org.springframework.boot.autoconfigure.data.neo4j.country.Country;
|
||||
|
||||
@NodeEntity
|
||||
public class City implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@GraphId
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String state;
|
||||
|
||||
private Country country;
|
||||
|
||||
private String map;
|
||||
|
||||
public City() {
|
||||
}
|
||||
|
||||
public City(String name, Country country) {
|
||||
this.name = name;
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
public Country getCountry() {
|
||||
return this.country;
|
||||
}
|
||||
|
||||
public String getMap() {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName() + "," + getState() + "," + getCountry();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.neo4j.city;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
|
||||
public interface CityRepository extends GraphRepository<City> {
|
||||
|
||||
Page<City> findAll(Pageable pageable);
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.neo4j.country;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.neo4j.ogm.annotation.GraphId;
|
||||
import org.neo4j.ogm.annotation.NodeEntity;
|
||||
|
||||
@NodeEntity
|
||||
public class Country implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@GraphId
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
public Country() {
|
||||
}
|
||||
|
||||
public Country(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.neo4j.country;
|
||||
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
|
||||
public interface CountryRepository extends GraphRepository<Country> {
|
||||
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.neo4j;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.neo4j.ogm.drivers.http.driver.HttpDriver;
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.neo4j.ogm.session.SessionFactory;
|
||||
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.neo4j.template.Neo4jOperations;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link Neo4jAutoConfiguration}. Tests can't use the embedded driver
|
||||
* as we use lucene 4 and Neo4j still requires 3.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Michael Hunger
|
||||
* @author Vince Bickers
|
||||
*/
|
||||
public class Neo4jAutoConfigurationTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultConfiguration() {
|
||||
load(null, "spring.data.neo4j.uri=http://localhost:8989");
|
||||
assertThat(this.context.getBeansOfType(Neo4jOperations.class)).hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(org.neo4j.ogm.config.Configuration.class)).hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(SessionFactory.class)).hasSize(1);
|
||||
assertThat(this.context.getBeanDefinition("scopedTarget.getSession").getScope()).isEqualTo("singleton");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customScope() {
|
||||
load(null, "spring.data.neo4j.uri=http://localhost:8989",
|
||||
"spring.data.neo4j.session.scope=prototype");
|
||||
assertThat(this.context.getBeanDefinition("scopedTarget.getSession").getScope()).isEqualTo("prototype");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customNeo4jOperations() {
|
||||
load(CustomNeo4jOperations.class);
|
||||
assertThat(this.context.getBean(Neo4jOperations.class))
|
||||
.isSameAs(this.context.getBean("myNeo4jOperations"));
|
||||
assertThat(this.context.getBeansOfType(org.neo4j.ogm.config.Configuration.class)).hasSize(0);
|
||||
assertThat(this.context.getBeansOfType(SessionFactory.class)).hasSize(0);
|
||||
assertThat(this.context.getBeansOfType(Session.class)).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customConfiguration() {
|
||||
load(CustomConfiguration.class);
|
||||
assertThat(this.context.getBean(org.neo4j.ogm.config.Configuration.class))
|
||||
.isSameAs(this.context.getBean("myConfiguration"));
|
||||
assertThat(this.context.getBeansOfType(Neo4jOperations.class)).hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(org.neo4j.ogm.config.Configuration.class)).hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(SessionFactory.class)).hasSize(1);
|
||||
}
|
||||
|
||||
public void load(Class<?> config, String... environment) {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(ctx, environment);
|
||||
if (config != null) {
|
||||
ctx.register(config);
|
||||
}
|
||||
ctx.register(PropertyPlaceholderAutoConfiguration.class,
|
||||
Neo4jAutoConfiguration.class);
|
||||
ctx.refresh();
|
||||
this.context = ctx;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomNeo4jOperations {
|
||||
|
||||
@Bean
|
||||
public Neo4jOperations myNeo4jOperations() {
|
||||
return mock(Neo4jOperations.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class CustomConfiguration {
|
||||
|
||||
@Bean
|
||||
public org.neo4j.ogm.config.Configuration myConfiguration() {
|
||||
org.neo4j.ogm.config.Configuration configuration = new org.neo4j.ogm.config.Configuration();
|
||||
configuration.driverConfiguration().setDriverClassName(HttpDriver.class.getName());
|
||||
return configuration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.neo4j;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
import com.hazelcast.util.Base64;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.neo4j.ogm.authentication.Credentials;
|
||||
import org.neo4j.ogm.config.Configuration;
|
||||
import org.neo4j.ogm.config.DriverConfiguration;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link Neo4jProperties}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class Neo4jPropertiesTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@After
|
||||
public void close() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultUseEmbeddedInMemoryIfAvailable() {
|
||||
Neo4jProperties properties = load(true);
|
||||
Configuration configuration = properties.createConfiguration();
|
||||
assertDriver(configuration, Neo4jProperties.EMBEDDED_DRIVER, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultUseHttpDriverIfEmbeddedDriverIsNotAvailable() {
|
||||
Neo4jProperties properties = load(false);
|
||||
Configuration configuration = properties.createConfiguration();
|
||||
assertDriver(configuration, Neo4jProperties.HTTP_DRIVER,
|
||||
Neo4jProperties.DEFAULT_HTTP_URI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpUriUseHttpServer() {
|
||||
Neo4jProperties properties = load(true,
|
||||
"spring.data.neo4j.uri=http://localhost:7474");
|
||||
Configuration configuration = properties.createConfiguration();
|
||||
assertDriver(configuration, Neo4jProperties.HTTP_DRIVER,
|
||||
"http://localhost:7474");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileUriUseEmbeddedServer() {
|
||||
Neo4jProperties properties = load(true,
|
||||
"spring.data.neo4j.uri=file://var/tmp/graph.db");
|
||||
Configuration configuration = properties.createConfiguration();
|
||||
assertDriver(configuration, Neo4jProperties.EMBEDDED_DRIVER,
|
||||
"file://var/tmp/graph.db");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void credentialsAreSet() {
|
||||
Neo4jProperties properties = load(true,
|
||||
"spring.data.neo4j.uri=http://localhost:7474",
|
||||
"spring.data.neo4j.username=user",
|
||||
"spring.data.neo4j.password=secret");
|
||||
Configuration configuration = properties.createConfiguration();
|
||||
assertDriver(configuration, Neo4jProperties.HTTP_DRIVER,
|
||||
"http://localhost:7474");
|
||||
assertCredentials(configuration, "user", "secret");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void credentialsAreSetFromUri() {
|
||||
Neo4jProperties properties = load(true,
|
||||
"spring.data.neo4j.uri=http://user:secret@my-server:7474");
|
||||
Configuration configuration = properties.createConfiguration();
|
||||
assertDriver(configuration, Neo4jProperties.HTTP_DRIVER,
|
||||
"http://user:secret@my-server:7474");
|
||||
assertCredentials(configuration, "user", "secret");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void embeddedModeDisabledUseHttpUri() {
|
||||
Neo4jProperties properties = load(true,
|
||||
"spring.data.neo4j.embedded.enabled=false");
|
||||
Configuration configuration = properties.createConfiguration();
|
||||
assertDriver(configuration, Neo4jProperties.HTTP_DRIVER,
|
||||
Neo4jProperties.DEFAULT_HTTP_URI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void embeddedModeWithRelativeLocation() {
|
||||
Neo4jProperties properties = load(true,
|
||||
"spring.data.neo4j.uri=target/neo4j/my.db");
|
||||
Configuration configuration = properties.createConfiguration();
|
||||
assertDriver(configuration, Neo4jProperties.EMBEDDED_DRIVER,
|
||||
"target/neo4j/my.db");
|
||||
}
|
||||
|
||||
private static void assertDriver(Configuration actual, String driver,
|
||||
String uri) {
|
||||
assertThat(actual).isNotNull();
|
||||
DriverConfiguration driverConfig = actual.driverConfiguration();
|
||||
assertThat(driverConfig.getDriverClassName()).isEqualTo(driver);
|
||||
assertThat(driverConfig.getURI()).isEqualTo(uri);
|
||||
}
|
||||
|
||||
private static void assertCredentials(Configuration actual, String username, String password) {
|
||||
Credentials credentials = actual.driverConfiguration().getCredentials();
|
||||
if (username == null & password == null) {
|
||||
assertThat(credentials).isNull();
|
||||
}
|
||||
else {
|
||||
assertThat(credentials).isNotNull();
|
||||
Object content = credentials.credentials();
|
||||
assertThat(content).isInstanceOf(String.class);
|
||||
String[] auth = new String(Base64.decode(((String) content)
|
||||
.getBytes())).split(":");
|
||||
assertThat(auth[0]).isEqualTo(username);
|
||||
assertThat(auth[1]).isEqualTo(password);
|
||||
assertThat(auth).hasSize(2);
|
||||
}
|
||||
}
|
||||
|
||||
public Neo4jProperties load(final boolean embeddedAvailable, String... environment) {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.setClassLoader(
|
||||
new URLClassLoader(new URL[0], getClass().getClassLoader()) {
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve)
|
||||
throws ClassNotFoundException {
|
||||
if (name.equals(Neo4jProperties.EMBEDDED_DRIVER)) {
|
||||
if (embeddedAvailable) {
|
||||
return TestEmbeddedDriver.class;
|
||||
}
|
||||
else {
|
||||
throw new ClassNotFoundException();
|
||||
}
|
||||
}
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
|
||||
});
|
||||
EnvironmentTestUtils.addEnvironment(ctx, environment);
|
||||
ctx.register(TestConfiguration.class);
|
||||
ctx.refresh();
|
||||
this.context = ctx;
|
||||
return this.context.getBean(Neo4jProperties.class);
|
||||
}
|
||||
|
||||
@org.springframework.context.annotation.Configuration
|
||||
@EnableConfigurationProperties(Neo4jProperties.class)
|
||||
static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
private static class TestEmbeddedDriver {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -55,6 +55,7 @@
|
|||
<cassandra-driver.version>2.1.9</cassandra-driver.version>
|
||||
<commons-beanutils.version>1.9.2</commons-beanutils.version>
|
||||
<commons-collections.version>3.2.2</commons-collections.version>
|
||||
<commons-codec.version>1.10</commons-codec.version>
|
||||
<commons-dbcp.version>1.4</commons-dbcp.version>
|
||||
<commons-dbcp2.version>2.1.1</commons-dbcp2.version>
|
||||
<commons-digester.version>2.1</commons-digester.version>
|
||||
|
@ -122,6 +123,7 @@
|
|||
<mongodb.version>2.14.1</mongodb.version>
|
||||
<mysql.version>5.1.38</mysql.version>
|
||||
<nekohtml.version>1.9.22</nekohtml.version>
|
||||
<neo4j-ogm.version>2.0.0-M04</neo4j-ogm.version>
|
||||
<postgresql.version>9.4.1208.jre7</postgresql.version>
|
||||
<reactor.version>2.0.7.RELEASE</reactor.version>
|
||||
<reactor-spring.version>2.0.7.RELEASE</reactor-spring.version>
|
||||
|
@ -325,6 +327,11 @@
|
|||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<version>1.4.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-neo4j</artifactId>
|
||||
<version>1.4.0.BUILD-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-rest</artifactId>
|
||||
|
@ -768,6 +775,11 @@
|
|||
<artifactId>commons-collections</artifactId>
|
||||
<version>${commons-collections.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>${commons-codec.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-dbcp</groupId>
|
||||
<artifactId>commons-dbcp</artifactId>
|
||||
|
@ -1760,6 +1772,26 @@
|
|||
<artifactId>mongo-java-driver</artifactId>
|
||||
<version>${mongodb.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-api</artifactId>
|
||||
<version>${neo4j-ogm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-compiler</artifactId>
|
||||
<version>${neo4j-ogm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-core</artifactId>
|
||||
<version>${neo4j-ogm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-http-driver</artifactId>
|
||||
<version>${neo4j-ogm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
|
|
|
@ -488,6 +488,11 @@
|
|||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-redis</artifactId>
|
||||
|
|
|
@ -536,6 +536,15 @@ content into your application; rather pick only the properties that you need.
|
|||
# DATA REDIS
|
||||
spring.data.redis.repositories.enabled=true # Enable Redis repositories.
|
||||
|
||||
# NEO4J ({sc-spring-boot-autoconfigure}/neo4j/Neo4jProperties.{sc-ext}[Neo4jProperties])
|
||||
spring.data.neo4j.compiler= # Compiler to use.
|
||||
spring.data.neo4j.embedded.enabled=true # Enable embedded mode if the embedded driver is available.
|
||||
spring.data.neo4j.password= # Login password of the server.
|
||||
spring.data.neo4j.repositories.enabled=true # Enable Neo4j repositories.
|
||||
spring.data.neo4j.session.scope=singleton # Scope (lifetime) of the session.
|
||||
spring.data.neo4j.uri= # URI used by the driver. Auto-detected by default.
|
||||
spring.data.neo4j.username= # Login user of the server.
|
||||
|
||||
# DATA REST ({sc-spring-boot-autoconfigure}/data/rest/RepositoryRestProperties.{sc-ext}[RepositoryRestProperties])
|
||||
spring.data.rest.base-path= # Base path to be used by Spring Data REST to expose repository resources.
|
||||
spring.data.rest.default-page-size= # Default size of pages.
|
||||
|
|
|
@ -2805,9 +2805,9 @@ http://projects.spring.io/spring-data-redis/[Redis],
|
|||
http://projects.spring.io/spring-data-gemfire/[Gemfire],
|
||||
http://projects.spring.io/spring-data-couchbase/[Couchbase] and
|
||||
http://projects.spring.io/spring-data-cassandra/[Cassandra].
|
||||
Spring Boot provides auto-configuration for Redis, MongoDB, Elasticsearch, Solr and
|
||||
Cassandra; you can make use of the other projects, but you will need to configure them
|
||||
yourself. Refer to the appropriate reference documentation at
|
||||
Spring Boot provides auto-configuration for Redis, MongoDB, Neo4j, Elasticsearch, Solr
|
||||
and Cassandra; you can make use of the other projects, but you will need to configure
|
||||
them yourself. Refer to the appropriate reference documentation at
|
||||
http://projects.spring.io/spring-data[projects.spring.io/spring-data].
|
||||
|
||||
|
||||
|
@ -3009,6 +3009,122 @@ Mongo instance's configuration and logging routing.
|
|||
|
||||
|
||||
|
||||
[[boot-features-neo4j]]
|
||||
=== Neo4j
|
||||
http://neo4j.com/[Neo4j] is an open-source NoSQL graph database that uses a rich data
|
||||
model of nodes related by first class relationships which is better suited for connected
|
||||
big data than traditional rdbms approaches. Spring Boot offers several conveniences for
|
||||
working with Neo4j, including the `spring-boot-starter-data-neo4j` '`Starter POM`'.
|
||||
|
||||
|
||||
|
||||
[[boot-features-connecting-to-neo4j]]
|
||||
==== Connecting to a Neo4j database
|
||||
You can inject an auto-configured `Neo4jSession`, `Session` or `Neo4jOperations` instance
|
||||
as you would any other Spring Bean. By default the instance will attempt to connect to a
|
||||
Neo4j server using `localhost:7474`:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Component
|
||||
public class MyBean {
|
||||
|
||||
private final Neo4jTemplate neo4jTemplate;
|
||||
|
||||
@Autowired
|
||||
public MyBean(Neo4jTemplate neo4jTemplate) {
|
||||
this.neo4jTemplate = neo4jTemplate;
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
You can take full control of the configuration by adding a
|
||||
`org.neo4j.ogm.config.Configuration` `@Bean` of your own. Also, adding a `@Bean` of type
|
||||
`Neo4jOperations` disables the auto-configuration.
|
||||
|
||||
You can configure the user and credentials to use via the `spring.data.couchbase.*`
|
||||
properties:
|
||||
|
||||
[source,properties,indent=0]
|
||||
----
|
||||
spring.data.neo4j.uri=http://my-server:7474
|
||||
spring.data.neo4j.username=neo4j
|
||||
spring.data.neo4j.password=secret
|
||||
----
|
||||
|
||||
[[boot-features-connecting-to-neo4j-embedded]]
|
||||
==== Using the embedded mode
|
||||
|
||||
NOTE: Neo4j's embedded mode is subject to a different licensing, make sure to review it
|
||||
before integrating the dependency in your application.
|
||||
|
||||
If you add `org.neo4j:neo4j-ogm-embedded-driver` to the dependencies of your application,
|
||||
Spring Boot will automatically configure an in-process embedded instance of Neo4j that
|
||||
will not persist any data when your application shuts down. You can explicitly disable
|
||||
that mode using `spring.data.neo4j.embedded.enabled=false`. You can also enable
|
||||
persistence for the embedded mode:
|
||||
|
||||
----
|
||||
spring.data.neo4j.uri=file://var/tmp/graph.db
|
||||
----
|
||||
|
||||
[[boot-features-neo4j-ogm-session]]
|
||||
==== Neo4jSession
|
||||
|
||||
By default, the lifetime of the session is scope to the application. If you are running a
|
||||
web application you can change it to scope or request easily:
|
||||
|
||||
----
|
||||
spring.data.neo4j.session.scope=session
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[boot-features-spring-data-neo4j-repositories]]
|
||||
==== Spring Data Neo4j repositories
|
||||
Spring Data includes repository support for Neo4j.
|
||||
|
||||
In fact, both Spring Data JPA and Spring Data Neo4j share the same common
|
||||
infrastructure; so you could take the JPA example from earlier and, assuming that `City`
|
||||
is now a Neo4j OGM `@NodeEntity` rather than a JPA `@Entity`, it will work in the same way.
|
||||
|
||||
TIP: You can customize entity scanning locations using the `@NodeEntityScan` annotation.
|
||||
|
||||
To enable repository support (and optionally support for `@Transactional`), add the following
|
||||
two annotations to your Spring configuration:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@EnableNeo4jRepositories(basePackages = "com.example.myapp.repository")
|
||||
@EnableTransactionManagement
|
||||
----
|
||||
|
||||
==== Repository example
|
||||
[source,java,indent=0]
|
||||
----
|
||||
package com.example.myapp.domain;
|
||||
|
||||
import org.springframework.data.domain.*;
|
||||
import org.springframework.data.repository.*;
|
||||
|
||||
public interface CityRepository extends GraphRepository<City> {
|
||||
|
||||
Page<City> findAll(Pageable pageable);
|
||||
|
||||
City findByNameAndCountry(String name, String country);
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
TIP: For complete details of Spring Data Neo4j, including its rich object mapping
|
||||
technologies, refer to their http://projects.spring.io/spring-data-neo4j/[reference
|
||||
documentation].
|
||||
|
||||
|
||||
|
||||
[[boot-features-gemfire]]
|
||||
=== Gemfire
|
||||
https://github.com/spring-projects/spring-data-gemfire[Spring Data Gemfire] provides
|
||||
|
|
|
@ -420,6 +420,9 @@ and Hibernate.
|
|||
|`spring-boot-starter-data-redis`
|
||||
|Support for the REDIS key-value data store, including `spring-data-redis`.
|
||||
|
||||
|`spring-boot-starter-data-neo4j`
|
||||
|Support for the Neo4j Graph Database, including `spring-data-neo4j`.
|
||||
|
||||
|`spring-boot-starter-data-rest`
|
||||
|Support for exposing Spring Data repositories over REST via `spring-data-rest-webmvc`.
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
<module>spring-boot-sample-data-gemfire</module>
|
||||
<module>spring-boot-sample-data-jpa</module>
|
||||
<module>spring-boot-sample-data-mongodb</module>
|
||||
<module>spring-boot-sample-data-neo4j</module>
|
||||
<module>spring-boot-sample-data-redis</module>
|
||||
<module>spring-boot-sample-data-rest</module>
|
||||
<module>spring-boot-sample-data-solr</module>
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
= Spring Boot Neo4j Sample
|
||||
|
||||
This sample demonstrates the integration of Neo4j with a simple entity. It
|
||||
expects a Neo4j instance running on `localhost`. If your neo4j instance
|
||||
requires authentication, update `application.properties` with your credentials:
|
||||
|
||||
```
|
||||
spring.data.neo4j.username=neo4j
|
||||
spring.data.neo4j.password=secret
|
||||
```
|
||||
|
||||
You can also locally add the embedded driver to embed Neo4j instead. Note
|
||||
that Spring Boot does not provide dependency management for that GPL-licensed
|
||||
library:
|
||||
|
||||
```
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-embedded-driver</artifactId>
|
||||
<version>${neo4j-ogm.version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
<parent>
|
||||
<!-- Your own application should inherit from spring-boot-starter-parent -->
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-samples</artifactId>
|
||||
<version>1.4.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-sample-data-neo4j</artifactId>
|
||||
<name>Spring Boot Data Neo4j Sample</name>
|
||||
<description>Spring Boot Data Neo4j Sample</description>
|
||||
<url>http://projects.spring.io/spring-boot/</url>
|
||||
<organization>
|
||||
<name>Pivotal Software, Inc.</name>
|
||||
<url>http://www.spring.io</url>
|
||||
</organization>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-neo4j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2012-2013 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
|
||||
*
|
||||
* http://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 sample.data.neo4j;
|
||||
|
||||
import org.neo4j.ogm.annotation.NodeEntity;
|
||||
import org.neo4j.ogm.annotation.GraphId;
|
||||
|
||||
@NodeEntity
|
||||
public class Customer {
|
||||
|
||||
@GraphId
|
||||
private Long id;
|
||||
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
public Customer() {
|
||||
}
|
||||
|
||||
public Customer(String firstName, String lastName) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Customer[id=%s, firstName='%s', lastName='%s']", id,
|
||||
firstName, lastName);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2012-2013 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
|
||||
*
|
||||
* http://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 sample.data.neo4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
|
||||
public interface CustomerRepository extends GraphRepository<Customer> {
|
||||
|
||||
public Customer findByFirstName(String firstName);
|
||||
|
||||
public List<Customer> findByLastName(String lastName);
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2012-2015 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
|
||||
*
|
||||
* http://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 sample.data.neo4j;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SampleNeo4jApplication implements CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
private CustomerRepository repository;
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
this.repository.deleteAll();
|
||||
|
||||
// save a couple of customers
|
||||
this.repository.save(new Customer("Alice", "Smith"));
|
||||
this.repository.save(new Customer("Bob", "Smith"));
|
||||
|
||||
// fetch all customers
|
||||
System.out.println("Customers found with findAll():");
|
||||
System.out.println("-------------------------------");
|
||||
for (Customer customer : this.repository.findAll()) {
|
||||
System.out.println(customer);
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
// fetch an individual customer
|
||||
System.out.println("Customer found with findByFirstName('Alice'):");
|
||||
System.out.println("--------------------------------");
|
||||
System.out.println(this.repository.findByFirstName("Alice"));
|
||||
|
||||
System.out.println("Customers found with findByLastName('Smith'):");
|
||||
System.out.println("--------------------------------");
|
||||
for (Customer customer : this.repository.findByLastName("Smith")) {
|
||||
System.out.println(customer);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(SampleNeo4jApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright 2012-2015 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
|
||||
*
|
||||
* http://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 sample.data.neo4j;
|
||||
|
||||
import java.net.ConnectException;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.test.rule.OutputCapture;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests for {@link SampleNeo4jApplication}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class SampleNeo4jApplicationTests {
|
||||
|
||||
@Rule
|
||||
public OutputCapture outputCapture = new OutputCapture();
|
||||
|
||||
@Test
|
||||
public void testDefaultSettings() throws Exception {
|
||||
try {
|
||||
SampleNeo4jApplication.main(new String[0]);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (!neo4jServerRunning(ex)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
String output = this.outputCapture.toString();
|
||||
assertTrue("Wrong output: " + output,
|
||||
output.contains("firstName='Alice', lastName='Smith'"));
|
||||
}
|
||||
|
||||
private boolean neo4jServerRunning(Throwable ex) {
|
||||
System.out.println(ex.getMessage());
|
||||
if (ex instanceof ConnectException) {
|
||||
return false;
|
||||
}
|
||||
return (ex.getCause() == null || neo4jServerRunning(ex.getCause()));
|
||||
}
|
||||
|
||||
}
|
|
@ -33,6 +33,7 @@
|
|||
<module>spring-boot-starter-data-gemfire</module>
|
||||
<module>spring-boot-starter-data-jpa</module>
|
||||
<module>spring-boot-starter-data-mongodb</module>
|
||||
<module>spring-boot-starter-data-neo4j</module>
|
||||
<module>spring-boot-starter-data-redis</module>
|
||||
<module>spring-boot-starter-data-rest</module>
|
||||
<module>spring-boot-starter-data-solr</module>
|
||||
|
@ -69,6 +70,7 @@
|
|||
<module>spring-boot-starter-websocket</module>
|
||||
<module>spring-boot-starter-ws</module>
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starters</artifactId>
|
||||
<version>1.4.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-starter-data-neo4j</artifactId>
|
||||
<name>Spring Boot Data Neo4j Starter</name>
|
||||
<description>Spring Boot Data Neo4j Starter</description>
|
||||
<url>http://projects.spring.io/spring-boot/</url>
|
||||
<organization>
|
||||
<name>Pivotal Software, Inc.</name>
|
||||
<url>http://www.spring.io</url>
|
||||
</organization>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-neo4j</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1 @@
|
|||
provides: spring-data-neo4j
|
|
@ -189,6 +189,11 @@
|
|||
<artifactId>liquibase-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.neo4j</groupId>
|
||||
<artifactId>neo4j-ogm-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.context.scan;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* A base {@link BeanPostProcessor} implementation that holds the packages to
|
||||
* use for a given component. An implementation must implement
|
||||
* {@link #postProcessBeforeInitialization(Object, String)} and update the
|
||||
* component responsible to manage the packages to scan.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public abstract class AbstractEntityScanBeanPostProcessor implements BeanPostProcessor, Ordered {
|
||||
|
||||
private final String[] packagesToScan;
|
||||
|
||||
protected AbstractEntityScanBeanPostProcessor(String[] packagesToScan) {
|
||||
this.packagesToScan = packagesToScan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the packages to use.
|
||||
* @return the packages to use.
|
||||
*/
|
||||
protected String[] getPackagesToScan() {
|
||||
return this.packagesToScan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* Copyright 2012-2016 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.
|
||||
|
@ -14,44 +14,69 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.orm.jpa;
|
||||
package org.springframework.boot.context.scan;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link ImportBeanDefinitionRegistrar} used by {@link EntityScan}.
|
||||
* A base {@link ImportBeanDefinitionRegistrar} used to collect the packages to
|
||||
* scan for a given component.
|
||||
* <p>
|
||||
* Expect to process an annotation type that defines a {@code basePackage} and
|
||||
* {@code basePackageClasses} attributes as well as a {@code value} alias of
|
||||
* {@code basePackage}.
|
||||
* <p>
|
||||
* The {@link ImportBeanDefinitionRegistrar} registers a single
|
||||
* {@link AbstractEntityScanBeanPostProcessor} implementation with the packages
|
||||
* to use.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Oliver Gierke
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.4.0
|
||||
* @see AbstractEntityScanBeanPostProcessor
|
||||
*/
|
||||
class EntityScanRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
public abstract class AbstractEntityScanRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
private final Class<? extends Annotation> annotationType;
|
||||
|
||||
private final String beanPostProcessorName;
|
||||
|
||||
private final Class<? extends AbstractEntityScanBeanPostProcessor> beanPostProcessorType;
|
||||
|
||||
/**
|
||||
* Create an instance.
|
||||
* @param annotationType the annotation to inspect
|
||||
* @param beanPostProcessorName the name of the bean post processor
|
||||
* @param beanPostProcessorType the type of the bean post processor implementation
|
||||
*/
|
||||
protected AbstractEntityScanRegistrar(Class<? extends Annotation> annotationType,
|
||||
String beanPostProcessorName,
|
||||
Class<? extends AbstractEntityScanBeanPostProcessor> beanPostProcessorType) {
|
||||
this.beanPostProcessorName = beanPostProcessorName;
|
||||
this.annotationType = annotationType;
|
||||
this.beanPostProcessorType = beanPostProcessorType;
|
||||
}
|
||||
|
||||
private static final String BEAN_NAME = "entityScanBeanPostProcessor";
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
|
||||
BeanDefinitionRegistry registry) {
|
||||
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
|
||||
if (!registry.containsBeanDefinition(BEAN_NAME)) {
|
||||
if (!registry.containsBeanDefinition(this.beanPostProcessorName)) {
|
||||
addEntityScanBeanPostProcessor(registry, packagesToScan);
|
||||
}
|
||||
else {
|
||||
|
@ -59,15 +84,16 @@ class EntityScanRegistrar implements ImportBeanDefinitionRegistrar {
|
|||
}
|
||||
}
|
||||
|
||||
private Set<String> getPackagesToScan(AnnotationMetadata metadata) {
|
||||
protected Set<String> getPackagesToScan(AnnotationMetadata metadata) {
|
||||
AnnotationAttributes attributes = AnnotationAttributes
|
||||
.fromMap(metadata.getAnnotationAttributes(EntityScan.class.getName()));
|
||||
.fromMap(metadata.getAnnotationAttributes(this.annotationType.getName()));
|
||||
String[] value = attributes.getStringArray("value");
|
||||
String[] basePackages = attributes.getStringArray("basePackages");
|
||||
Class<?>[] basePackageClasses = attributes.getClassArray("basePackageClasses");
|
||||
if (!ObjectUtils.isEmpty(value)) {
|
||||
Assert.state(ObjectUtils.isEmpty(basePackages),
|
||||
"@EntityScan basePackages and value attributes are mutually exclusive");
|
||||
Assert.state(ObjectUtils.isEmpty(basePackages), String.format(
|
||||
"@%s basePackages and value attributes are mutually exclusive",
|
||||
this.annotationType.getSimpleName()));
|
||||
}
|
||||
Set<String> packagesToScan = new LinkedHashSet<String>();
|
||||
packagesToScan.addAll(Arrays.asList(value));
|
||||
|
@ -85,20 +111,20 @@ class EntityScanRegistrar implements ImportBeanDefinitionRegistrar {
|
|||
private void addEntityScanBeanPostProcessor(BeanDefinitionRegistry registry,
|
||||
Set<String> packagesToScan) {
|
||||
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
|
||||
beanDefinition.setBeanClass(EntityScanBeanPostProcessor.class);
|
||||
beanDefinition.setBeanClass(this.beanPostProcessorType);
|
||||
beanDefinition.getConstructorArgumentValues()
|
||||
.addGenericArgumentValue(toArray(packagesToScan));
|
||||
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
// We don't need this one to be post processed otherwise it can cause a
|
||||
// cascade of bean instantiation that we would rather avoid.
|
||||
beanDefinition.setSynthetic(true);
|
||||
registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
|
||||
registry.registerBeanDefinition(this.beanPostProcessorName, beanDefinition);
|
||||
}
|
||||
|
||||
private void updateEntityScanBeanPostProcessor(BeanDefinitionRegistry registry,
|
||||
Set<String> packagesToScan) {
|
||||
BeanDefinition definition = registry.getBeanDefinition(BEAN_NAME);
|
||||
ValueHolder constructorArguments = definition.getConstructorArgumentValues()
|
||||
BeanDefinition definition = registry.getBeanDefinition(this.beanPostProcessorName);
|
||||
ConstructorArgumentValues.ValueHolder constructorArguments = definition.getConstructorArgumentValues()
|
||||
.getGenericArgumentValue(String[].class);
|
||||
Set<String> mergedPackages = new LinkedHashSet<String>();
|
||||
mergedPackages.addAll(Arrays.asList((String[]) constructorArguments.getValue()));
|
||||
|
@ -110,52 +136,4 @@ class EntityScanRegistrar implements ImportBeanDefinitionRegistrar {
|
|||
return set.toArray(new String[set.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link BeanPostProcessor} to set
|
||||
* {@link LocalContainerEntityManagerFactoryBean#setPackagesToScan(String...)} based
|
||||
* on an {@link EntityScan} annotation.
|
||||
*/
|
||||
static class EntityScanBeanPostProcessor
|
||||
implements BeanPostProcessor, SmartInitializingSingleton, Ordered {
|
||||
|
||||
private final String[] packagesToScan;
|
||||
|
||||
private boolean processed;
|
||||
|
||||
EntityScanBeanPostProcessor(String[] packagesToScan) {
|
||||
this.packagesToScan = packagesToScan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof LocalContainerEntityManagerFactoryBean) {
|
||||
LocalContainerEntityManagerFactoryBean factoryBean = (LocalContainerEntityManagerFactoryBean) bean;
|
||||
factoryBean.setPackagesToScan(this.packagesToScan);
|
||||
this.processed = true;
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
Assert.state(this.processed,
|
||||
"Unable to configure "
|
||||
+ "LocalContainerEntityManagerFactoryBean from @EntityScan, "
|
||||
+ "ensure an appropriate bean is registered.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for component scanning.
|
||||
*/
|
||||
package org.springframework.boot.context.scan;
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.neo4j;
|
||||
|
||||
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.neo4j.ogm.session.SessionFactory;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Configures the {@link SessionFactory} to scan for node entity
|
||||
* classes in the classpath. This annotation provides an alternative to manually setting
|
||||
* {@link SessionFactoryProvider#setPackagesToScan(String...)} and is
|
||||
* particularly useful if you want to configure entity scanning in a type-safe way, or if
|
||||
* your {@link SessionFactory} is auto-configured.
|
||||
* <p>
|
||||
* A {@link SessionFactoryProvider} must be configured within your Spring
|
||||
* ApplicationContext in order to use entity scanning. Furthermore, any existing
|
||||
* {@code packagesToScan} setting will be replaced.
|
||||
* <p>
|
||||
* One of {@link #basePackageClasses()}, {@link #basePackages()} or its alias
|
||||
* {@link #value()} may be specified to define specific packages to scan. If specific
|
||||
* packages are not defined scanning will occur from the package of the class with this
|
||||
* annotation.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.4.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Import(NodeEntityScanRegistrar.class)
|
||||
public @interface NodeEntityScan {
|
||||
|
||||
/**
|
||||
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
|
||||
* declarations e.g.: {@code @NodeEntityScan("org.my.pkg")} instead of
|
||||
* {@code @NodeEntityScan(basePackages="org.my.pkg")}.
|
||||
* @return the base packages to scan
|
||||
*/
|
||||
String[] value() default {};
|
||||
|
||||
/**
|
||||
* Base packages to scan for node entities. {@link #value()} is an alias for (and
|
||||
* mutually exclusive with) this attribute.
|
||||
* <p>
|
||||
* Use {@link #basePackageClasses()} for a type-safe alternative to String-based
|
||||
* package names.
|
||||
* @return the base packages to scan
|
||||
*/
|
||||
String[] basePackages() default {};
|
||||
|
||||
/**
|
||||
* Type-safe alternative to {@link #basePackages()} for specifying the packages to
|
||||
* scan for node entities. The package of each class specified will be scanned.
|
||||
* <p>
|
||||
* Consider creating a special no-op marker class or interface in each package that
|
||||
* serves no purpose other than being referenced by this attribute.
|
||||
* @return classes from the base packages to scan
|
||||
*/
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.neo4j;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.context.scan.AbstractEntityScanBeanPostProcessor;
|
||||
import org.springframework.boot.context.scan.AbstractEntityScanRegistrar;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link ImportBeanDefinitionRegistrar} used by {@link NodeEntityScan}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class NodeEntityScanRegistrar extends AbstractEntityScanRegistrar {
|
||||
|
||||
NodeEntityScanRegistrar() {
|
||||
super(NodeEntityScan.class, "nodeEntityScanBeanPostProcessor", NodeEntityScanBeanPostProcessor.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link BeanPostProcessor} to set
|
||||
* {@link SessionFactoryProvider#setPackagesToScan(String...)} based
|
||||
* on an {@link NodeEntityScan} annotation.
|
||||
*/
|
||||
static class NodeEntityScanBeanPostProcessor extends AbstractEntityScanBeanPostProcessor
|
||||
implements SmartInitializingSingleton {
|
||||
|
||||
private boolean processed;
|
||||
|
||||
NodeEntityScanBeanPostProcessor(String[] packagesToScan) {
|
||||
super(packagesToScan);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof SessionFactoryProvider) {
|
||||
SessionFactoryProvider provider = (SessionFactoryProvider) bean;
|
||||
provider.setPackagesToScan(getPackagesToScan());
|
||||
this.processed = true;
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
Assert.state(this.processed,
|
||||
"Unable to configure "
|
||||
+ "SessionFactoryFactoryBean from @NodeEntityScan, "
|
||||
+ "ensure an appropriate bean is registered.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.neo4j;
|
||||
|
||||
import org.neo4j.ogm.config.Configuration;
|
||||
import org.neo4j.ogm.session.SessionFactory;
|
||||
|
||||
/**
|
||||
* Provide a a Neo4j {@link SessionFactory} instance based on a
|
||||
* configurable {@link Configuration} and custom packages to scan.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.4.0
|
||||
* @see NodeEntityScan
|
||||
*/
|
||||
public class SessionFactoryProvider {
|
||||
|
||||
private Configuration configuration;
|
||||
|
||||
private String[] packagesToScan;
|
||||
|
||||
/**
|
||||
* Set the configuration to use.
|
||||
* @param configuration the configuration
|
||||
*/
|
||||
public void setConfiguration(Configuration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the packages to scan.
|
||||
* @param packagesToScan the packages to scan
|
||||
*/
|
||||
public void setPackagesToScan(String[] packagesToScan) {
|
||||
this.packagesToScan = packagesToScan;
|
||||
}
|
||||
|
||||
public SessionFactory getSessionFactory() {
|
||||
return new SessionFactory(this.configuration, this.packagesToScan);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Neo4j support classes.
|
||||
*/
|
||||
package org.springframework.boot.neo4j;
|
|
@ -46,7 +46,7 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
|||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Import(EntityScanRegistrar.class)
|
||||
@Import(JpaEntityScanRegistrar.class)
|
||||
public @interface EntityScan {
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 2012-2015 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.orm.jpa;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.context.scan.AbstractEntityScanBeanPostProcessor;
|
||||
import org.springframework.boot.context.scan.AbstractEntityScanRegistrar;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link ImportBeanDefinitionRegistrar} used by {@link EntityScan}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class JpaEntityScanRegistrar extends AbstractEntityScanRegistrar {
|
||||
|
||||
JpaEntityScanRegistrar() {
|
||||
super(EntityScan.class, "entityScanBeanPostProcessor", JpaEntityScanBeanPostProcessor.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link BeanPostProcessor} to set
|
||||
* {@link LocalContainerEntityManagerFactoryBean#setPackagesToScan(String...)} based
|
||||
* on an {@link EntityScan} annotation.
|
||||
*/
|
||||
static class JpaEntityScanBeanPostProcessor extends AbstractEntityScanBeanPostProcessor
|
||||
implements SmartInitializingSingleton {
|
||||
|
||||
private boolean processed;
|
||||
|
||||
JpaEntityScanBeanPostProcessor(String[] packagesToScan) {
|
||||
super(packagesToScan);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof LocalContainerEntityManagerFactoryBean) {
|
||||
LocalContainerEntityManagerFactoryBean factoryBean = (LocalContainerEntityManagerFactoryBean) bean;
|
||||
factoryBean.setPackagesToScan(getPackagesToScan());
|
||||
this.processed = true;
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
Assert.state(this.processed,
|
||||
"Unable to configure "
|
||||
+ "LocalContainerEntityManagerFactoryBean from @EntityScan, "
|
||||
+ "ensure an appropriate bean is registered.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.context.scan;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* EntityScan test annotation.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Import(TestEntityScanRegistrar.class)
|
||||
public @interface TestEntityScan {
|
||||
|
||||
String[] value() default {};
|
||||
|
||||
String[] basePackages() default {};
|
||||
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.context.scan;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
|
||||
/**
|
||||
* Test implementation of {@link AbstractEntityScanRegistrar}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class TestEntityScanRegistrar extends AbstractEntityScanRegistrar {
|
||||
|
||||
static final String BEAN_NAME = "testEntityScanBeanPostProcessor";
|
||||
|
||||
TestEntityScanRegistrar() {
|
||||
super(TestEntityScan.class, BEAN_NAME, TestEntityScanBeanPostProcessor.class);
|
||||
}
|
||||
|
||||
static class TestFactoryBean {
|
||||
private String[] packagesToScan;
|
||||
|
||||
public void setPackagesToScan(String... packagesToScan) {
|
||||
this.packagesToScan = packagesToScan;
|
||||
}
|
||||
|
||||
public String[] getPackagesToScan() {
|
||||
return this.packagesToScan;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestEntityScanBeanPostProcessor extends AbstractEntityScanBeanPostProcessor {
|
||||
|
||||
TestEntityScanBeanPostProcessor(String[] packagesToScan) {
|
||||
super(packagesToScan);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof TestFactoryBean) {
|
||||
TestFactoryBean factoryBean = (TestFactoryBean) bean;
|
||||
factoryBean.setPackagesToScan(getPackagesToScan());
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.context.scan;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.boot.context.scan.TestEntityScanRegistrar.TestFactoryBean;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link TestEntityScan}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class TestEntityScanTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@After
|
||||
public void closeContext() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValue() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(ValueConfig.class);
|
||||
assertSetPackagesToScan("com.mycorp.entity");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basePackages() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(BasePackagesConfig.class);
|
||||
assertSetPackagesToScan("com.mycorp.entity2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basePackageClasses() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(
|
||||
BasePackageClassesConfig.class);
|
||||
assertSetPackagesToScan(getClass().getPackage().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromConfigurationClass() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(FromConfigConfig.class);
|
||||
assertSetPackagesToScan(getClass().getPackage().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueAndBasePackagesThrows() throws Exception {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage("@TestEntityScan basePackages and value "
|
||||
+ "attributes are mutually exclusive");
|
||||
this.context = new AnnotationConfigApplicationContext(ValueAndBasePackages.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueAndBasePackageClassesMerges() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(
|
||||
ValueAndBasePackageClasses.class);
|
||||
assertSetPackagesToScan("com.mycorp.entity", getClass().getPackage().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basePackageAndBasePackageClassesMerges() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(
|
||||
BasePackagesAndBasePackageClasses.class);
|
||||
assertSetPackagesToScan("com.mycorp.entity2", getClass().getPackage().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void considersMultipleAnnotations() {
|
||||
this.context = new AnnotationConfigApplicationContext(MultiScanFirst.class,
|
||||
MultiScanSecond.class);
|
||||
assertSetPackagesToScan("foo", "bar");
|
||||
}
|
||||
|
||||
private void assertSetPackagesToScan(String... expected) {
|
||||
String[] actual = this.context
|
||||
.getBean(TestFactoryBean.class)
|
||||
.getPackagesToScan();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class BaseConfig {
|
||||
|
||||
@Bean
|
||||
public TestFactoryBean testFactoryBean() {
|
||||
return new TestFactoryBean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestEntityScan("com.mycorp.entity")
|
||||
static class ValueConfig extends BaseConfig {
|
||||
}
|
||||
|
||||
@TestEntityScan(basePackages = "com.mycorp.entity2")
|
||||
static class BasePackagesConfig extends BaseConfig {
|
||||
}
|
||||
|
||||
@TestEntityScan(basePackageClasses = TestEntityScanTests.class)
|
||||
static class BasePackageClassesConfig extends BaseConfig {
|
||||
}
|
||||
|
||||
@TestEntityScan
|
||||
static class FromConfigConfig extends BaseConfig {
|
||||
}
|
||||
|
||||
@TestEntityScan(value = "com.mycorp.entity", basePackages = "com.mycorp")
|
||||
static class ValueAndBasePackages extends BaseConfig {
|
||||
}
|
||||
|
||||
@TestEntityScan(value = "com.mycorp.entity", basePackageClasses = TestEntityScanTests.class)
|
||||
static class ValueAndBasePackageClasses extends BaseConfig {
|
||||
}
|
||||
|
||||
@TestEntityScan(basePackages = "com.mycorp.entity2", basePackageClasses = TestEntityScanTests.class)
|
||||
static class BasePackagesAndBasePackageClasses extends BaseConfig {
|
||||
}
|
||||
|
||||
@TestEntityScan(basePackages = "foo")
|
||||
static class MultiScanFirst extends BaseConfig {
|
||||
}
|
||||
|
||||
@TestEntityScan(basePackages = "bar")
|
||||
static class MultiScanSecond extends BaseConfig {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.neo4j;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link NodeEntityScan}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class NodeEntityScanTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@After
|
||||
public void closeContext() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleValue() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(ValueConfig.class);
|
||||
assertSetPackagesToScan("com.mycorp.entity");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void needsSessionFactoryFactory() throws Exception {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage("Unable to configure "
|
||||
+ "SessionFactoryFactoryBean from @NodeEntityScan, "
|
||||
+ "ensure an appropriate bean is registered.");
|
||||
this.context = new AnnotationConfigApplicationContext(MissingSessionFactory.class);
|
||||
}
|
||||
|
||||
private void assertSetPackagesToScan(String... expected) {
|
||||
String[] actual = this.context
|
||||
.getBean(TestSessionFactoryProvider.class)
|
||||
.getPackagesToScan();
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class BaseConfig {
|
||||
|
||||
@Bean
|
||||
public SessionFactoryProvider sessionFactoryFactoryBean() {
|
||||
return new TestSessionFactoryProvider();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@NodeEntityScan("com.mycorp.entity")
|
||||
static class ValueConfig extends BaseConfig {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@NodeEntityScan("com.mycorp.entity")
|
||||
static class MissingSessionFactory {
|
||||
}
|
||||
|
||||
|
||||
private static class TestSessionFactoryProvider
|
||||
extends SessionFactoryProvider {
|
||||
|
||||
private String[] packagesToScan;
|
||||
|
||||
@Override
|
||||
public void setPackagesToScan(String... packagesToScan) {
|
||||
this.packagesToScan = packagesToScan;
|
||||
}
|
||||
|
||||
public String[] getPackagesToScan() {
|
||||
return this.packagesToScan;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@ package org.springframework.boot.orm.jpa;
|
|||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
@ -37,6 +38,7 @@ import static org.mockito.Mockito.mock;
|
|||
* Tests for {@link EntityScan}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class EntityScanTests {
|
||||
|
||||
|
@ -45,53 +47,19 @@ public class EntityScanTests {
|
|||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@After
|
||||
public void closeContext() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValue() throws Exception {
|
||||
public void simpleValue() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(ValueConfig.class);
|
||||
assertSetPackagesToScan("com.mycorp.entity");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basePackages() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(BasePackagesConfig.class);
|
||||
assertSetPackagesToScan("com.mycorp.entity2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basePackageClasses() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(
|
||||
BasePackageClassesConfig.class);
|
||||
assertSetPackagesToScan(getClass().getPackage().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromConfigurationClass() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(FromConfigConfig.class);
|
||||
assertSetPackagesToScan(getClass().getPackage().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueAndBasePackagesThrows() throws Exception {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage("@EntityScan basePackages and value "
|
||||
+ "attributes are mutually exclusive");
|
||||
this.context = new AnnotationConfigApplicationContext(ValueAndBasePackages.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueAndBasePackageClassesMerges() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(
|
||||
ValueAndBasePackageClasses.class);
|
||||
assertSetPackagesToScan("com.mycorp.entity", getClass().getPackage().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basePackageAndBasePackageClassesMerges() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(
|
||||
BasePackagesAndBasePackageClasses.class);
|
||||
assertSetPackagesToScan("com.mycorp.entity2", getClass().getPackage().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void needsEntityManageFactory() throws Exception {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
|
@ -108,13 +76,6 @@ public class EntityScanTests {
|
|||
assertSetPackagesToScan("com.mycorp.entity");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void considersMultipleEntityScanAnnotations() {
|
||||
this.context = new AnnotationConfigApplicationContext(MultiScanFirst.class,
|
||||
MultiScanSecond.class);
|
||||
assertSetPackagesToScan("foo", "bar");
|
||||
}
|
||||
|
||||
private void assertSetPackagesToScan(String... expected) {
|
||||
String[] actual = this.context
|
||||
.getBean(TestLocalContainerEntityManagerFactoryBean.class)
|
||||
|
@ -136,30 +97,6 @@ public class EntityScanTests {
|
|||
static class ValueConfig extends BaseConfig {
|
||||
}
|
||||
|
||||
@EntityScan(basePackages = "com.mycorp.entity2")
|
||||
static class BasePackagesConfig extends BaseConfig {
|
||||
}
|
||||
|
||||
@EntityScan(basePackageClasses = EntityScanTests.class)
|
||||
static class BasePackageClassesConfig extends BaseConfig {
|
||||
}
|
||||
|
||||
@EntityScan
|
||||
static class FromConfigConfig extends BaseConfig {
|
||||
}
|
||||
|
||||
@EntityScan(value = "com.mycorp.entity", basePackages = "com.mycorp")
|
||||
static class ValueAndBasePackages extends BaseConfig {
|
||||
}
|
||||
|
||||
@EntityScan(value = "com.mycorp.entity", basePackageClasses = EntityScanTests.class)
|
||||
static class ValueAndBasePackageClasses extends BaseConfig {
|
||||
}
|
||||
|
||||
@EntityScan(basePackages = "com.mycorp.entity2", basePackageClasses = EntityScanTests.class)
|
||||
static class BasePackagesAndBasePackageClasses extends BaseConfig {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EntityScan("com.mycorp.entity")
|
||||
static class MissingEntityManager {
|
||||
|
@ -195,16 +132,6 @@ public class EntityScanTests {
|
|||
}
|
||||
}
|
||||
|
||||
@EntityScan(basePackages = "foo")
|
||||
static class MultiScanFirst extends BaseConfig {
|
||||
|
||||
}
|
||||
|
||||
@EntityScan(basePackages = "bar")
|
||||
static class MultiScanSecond extends BaseConfig {
|
||||
|
||||
}
|
||||
|
||||
private static class TestLocalContainerEntityManagerFactoryBean
|
||||
extends LocalContainerEntityManagerFactoryBean {
|
||||
|
||||
|
|
Loading…
Reference in New Issue