jboss-repository
JBoss Public Repository
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/annotation/RelatedTo.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/annotation/RelatedTo.java
index 0069041f3..315a81ba7 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/annotation/RelatedTo.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/annotation/RelatedTo.java
@@ -16,14 +16,14 @@
package org.springframework.data.graph.annotation;
+import org.springframework.data.graph.core.Direction;
+import org.springframework.data.graph.core.NodeBacked;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import org.springframework.data.graph.core.Direction;
-import org.springframework.data.graph.core.NodeBacked;
-
/**
* Annotation for {@link org.springframework.data.graph.annotation.NodeEntity} fields that relate to other entities via
* relationships. Works for one-to-one and one-to-many relationships. It is optionally possible to define the relationship type,
@@ -31,10 +31,11 @@ import org.springframework.data.graph.core.NodeBacked;
*
* Collection based one-to-many relationships return managed collections that reflect addition and removal to the underlying relationships.
*
+ * Examples:
*
- * @RelatedTo([type="friends"], elementClass=Person.class)
+ * @RelatedTo(elementClass=Person.class)
* Collection<Person> friends;
- * @RelatedTo([type="spouse"], [elementClass=Person.class])
+ * @RelatedTo(type="partner")
* Person spouse;
*
@@ -47,7 +48,7 @@ public @interface RelatedTo {
/**
* @return name of the relationship type, optional, can be inferred from the field name
*/
- String type();
+ String type() default "";
/**
* @return direction for the relationship, by default outgoing
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/annotation/RelatedToVia.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/annotation/RelatedToVia.java
index 318bc997d..1d73667f8 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/annotation/RelatedToVia.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/annotation/RelatedToVia.java
@@ -52,5 +52,5 @@ public @interface RelatedToVia {
/**
* @return target relationship entity class
*/
- Class extends RelationshipBacked> elementClass() default RelationshipBacked.class;
+ Class extends RelationshipBacked> elementClass();
}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/ConfigurationCheck.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/ConfigurationCheck.java
new file mode 100644
index 000000000..c7d0be8d3
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/ConfigurationCheck.java
@@ -0,0 +1,67 @@
+package org.springframework.data.graph.neo4j.config;
+
+import org.neo4j.graphdb.Transaction;
+import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionStatus;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * Validates correct configuration of Neo4j and Spring, especially transaction-managers
+ */
+public class ConfigurationCheck {
+ GraphDatabaseContext graphDatabaseContext;
+ PlatformTransactionManager transactionManager;
+
+ public ConfigurationCheck(GraphDatabaseContext graphDatabaseContext, PlatformTransactionManager transactionManager) {
+ this.graphDatabaseContext = graphDatabaseContext;
+ this.transactionManager = transactionManager;
+ }
+
+ @PostConstruct
+ private void checkConfiguration() {
+ checkInjection();
+ checkSpringTransactionManager();
+ checkNeo4jTransactionManager();
+ }
+
+ private void checkInjection() {
+ assert graphDatabaseContext.getGraphDatabaseService()!=null : "graphDatabaseService not correctly configured, please refer to the manual, setup section";
+ }
+
+ private void checkSpringTransactionManager() {
+ try {
+ TransactionStatus transaction = transactionManager.getTransaction(null);
+ updateStartTime();
+ transactionManager.commit(transaction);
+ } catch(Exception e) {
+ AssertionError error = new AssertionError("transactionManager not correctly configured, please refer to the manual, setup section");
+ error.initCause(e);
+ throw error;
+ }
+ }
+
+ private void checkNeo4jTransactionManager() {
+ Transaction tx = null;
+ try {
+ tx = graphDatabaseContext.beginTx();
+ updateStartTime();
+ tx.success();
+ } catch (Exception e) {
+ AssertionError error = new AssertionError("transactionManager not correctly configured, please refer to the manual, setup section");
+ error.initCause(e);
+ throw error;
+ } finally {
+ try {
+ if (tx != null) tx.finish();
+ } catch(Exception e) {
+ // ignore
+ }
+ }
+ }
+
+ private void updateStartTime() {
+ graphDatabaseContext.getReferenceNode().setProperty("startTime", System.currentTimeMillis());
+ }
+}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/DataGraphBeanDefinitionParser.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/DataGraphBeanDefinitionParser.java
index eebb1bbf2..614ba28c5 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/DataGraphBeanDefinitionParser.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/DataGraphBeanDefinitionParser.java
@@ -1,10 +1,14 @@
package org.springframework.data.graph.neo4j.config;
import org.neo4j.kernel.EmbeddedGraphDatabase;
+import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.w3c.dom.Element;
import static org.springframework.util.StringUtils.hasText;
@@ -15,12 +19,29 @@ public class DataGraphBeanDefinitionParser extends AbstractBeanDefinitionParser
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext context) {
- BeanDefinitionBuilder configBuilder = BeanDefinitionBuilder.rootBeanDefinition(Neo4jConfiguration.class);
+ BeanDefinitionBuilder configBuilder = createConfigurationBeanDefinition();
setupGraphDatabase(element, context, configBuilder);
setupEntityManagerFactory(element, configBuilder);
+ setupConfigurationClassPostProcessor(context);
return getSourcedBeanDefinition(configBuilder, element, context);
}
+ private BeanDefinitionBuilder createConfigurationBeanDefinition() {
+ BeanDefinitionBuilder configBuilder = BeanDefinitionBuilder.rootBeanDefinition(Neo4jConfiguration.class);
+ configBuilder.setAutowireMode(Autowire.BY_TYPE.value());
+ return configBuilder;
+ }
+
+ private void setupConfigurationClassPostProcessor(final ParserContext parserContext) {
+ BeanDefinitionRegistry beanDefinitionRegistry = parserContext.getRegistry();
+
+ BeanDefinitionBuilder configurationClassPostProcessor = BeanDefinitionBuilder.rootBeanDefinition(ConfigurationClassPostProcessor.class);
+ BeanNameGenerator beanNameGenerator = parserContext.getReaderContext().getReader().getBeanNameGenerator();
+ AbstractBeanDefinition configurationClassPostProcessorBeanDefinition = configurationClassPostProcessor.getBeanDefinition();
+ String beanName = beanNameGenerator.generateBeanName(configurationClassPostProcessorBeanDefinition, beanDefinitionRegistry);
+ beanDefinitionRegistry.registerBeanDefinition(beanName, configurationClassPostProcessorBeanDefinition);
+ }
+
@Override
protected boolean shouldGenerateId() {
return true;
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/Neo4jConfiguration.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/Neo4jConfiguration.java
index 331903284..0a7e33cb4 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/Neo4jConfiguration.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/Neo4jConfiguration.java
@@ -17,32 +17,32 @@
package org.springframework.data.graph.neo4j.config;
import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.graphdb.Node;
import org.neo4j.kernel.impl.transaction.SpringTransactionManager;
import org.neo4j.kernel.impl.transaction.UserTransactionImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.data.graph.core.NodeBacked;
import org.springframework.data.graph.neo4j.fieldaccess.Neo4jConversionServiceFactoryBean;
import org.springframework.data.graph.neo4j.fieldaccess.NodeDelegatingFieldAccessorFactory;
import org.springframework.data.graph.neo4j.fieldaccess.NodeEntityStateFactory;
import org.springframework.data.graph.neo4j.fieldaccess.RelationshipEntityStateFactory;
import org.springframework.data.graph.neo4j.finder.FinderFactory;
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
-import org.springframework.data.graph.neo4j.support.SubReferenceNodeTypeStrategy;
+import org.springframework.data.graph.neo4j.support.NodeTypeStrategyFactoryBean;
import org.springframework.data.graph.neo4j.support.node.Neo4jConstructorGraphEntityInstantiator;
import org.springframework.data.graph.neo4j.support.node.Neo4jNodeBacking;
import org.springframework.data.graph.neo4j.support.node.PartialNeo4jEntityInstantiator;
import org.springframework.data.graph.neo4j.support.relationship.ConstructorBypassingGraphRelationshipInstantiator;
import org.springframework.data.graph.neo4j.support.relationship.Neo4jRelationshipBacking;
import org.springframework.data.graph.neo4j.transaction.ChainedTransactionManager;
-import org.springframework.orm.jpa.EntityManagerFactoryUtils;
import org.springframework.orm.jpa.JpaTransactionManager;
-import org.springframework.persistence.transaction.NaiveDoubleTransactionManager;
+import org.springframework.data.persistence.EntityInstantiator;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager;
-import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.validation.Validator;
@@ -82,7 +82,7 @@ public class Neo4jConfiguration {
}
public boolean isUsingCrossStorePersistence() {
- return entityManagerFactory!=null;
+ return entityManagerFactory != null;
}
@Bean
@@ -90,20 +90,25 @@ public class Neo4jConfiguration {
GraphDatabaseContext gdc = new GraphDatabaseContext();
gdc.setGraphDatabaseService(getGraphDatabaseService());
gdc.setRelationshipEntityInstantiator(new ConstructorBypassingGraphRelationshipInstantiator());
- if (isUsingCrossStorePersistence()) {
- gdc.setGraphEntityInstantiator(new PartialNeo4jEntityInstantiator(new Neo4jConstructorGraphEntityInstantiator(), entityManagerFactory));
- }
- else {
- gdc.setGraphEntityInstantiator(new Neo4jConstructorGraphEntityInstantiator());
- }
+ EntityInstantiator graphEntityInstantiator = getGraphEntityInstantiator();
+ gdc.setGraphEntityInstantiator(graphEntityInstantiator);
gdc.setConversionService(new Neo4jConversionServiceFactoryBean().getObject());
- gdc.setNodeTypeStrategy(new SubReferenceNodeTypeStrategy(gdc));
+ NodeTypeStrategyFactoryBean nodeTypeStrategyFactoryBean = new NodeTypeStrategyFactoryBean(graphDatabaseService, graphEntityInstantiator);
+ gdc.setNodeTypeStrategy(nodeTypeStrategyFactoryBean.getObject());
if (validator!=null) {
gdc.setValidator(validator);
}
return gdc;
}
+ private EntityInstantiator getGraphEntityInstantiator() {
+ if (isUsingCrossStorePersistence()) {
+ return new PartialNeo4jEntityInstantiator(new Neo4jConstructorGraphEntityInstantiator(), entityManagerFactory);
+ } else {
+ return new Neo4jConstructorGraphEntityInstantiator();
+ }
+ }
+
@Bean
public FinderFactory finderFactory(GraphDatabaseContext graphDatabaseContext) throws Exception {
return new FinderFactory(graphDatabaseContext);
@@ -149,4 +154,9 @@ public class Neo4jConfiguration {
return transactionManager;
}
}
+
+ @Bean
+ public ConfigurationCheck configurationCheck() throws Exception {
+ return new ConfigurationCheck(graphDatabaseContext(),transactionManager());
+ }
}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/DefaultEntityState.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/DefaultEntityState.java
index ce2615b71..2c9e19766 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/DefaultEntityState.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/DefaultEntityState.java
@@ -43,8 +43,8 @@ public abstract class DefaultEntityState, STAT
this.entity = entity;
this.type = type;
fieldAccessorFactoryProviders = delegatingFieldAccessorFactory.accessorFactoriesFor(type);
- this.fieldAccessors= fieldAccessorFactoryProviders.getFieldAccessors();
- this.fieldAccessorListeners= fieldAccessorFactoryProviders.getFieldAccessListeners();
+ this.fieldAccessors = fieldAccessorFactoryProviders.getFieldAccessors();
+ this.fieldAccessorListeners = fieldAccessorFactoryProviders.getFieldAccessListeners();
}
@Override
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/DelegatingFieldAccessorFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/DelegatingFieldAccessorFactory.java
index e2996d827..bc48e4bae 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/DelegatingFieldAccessorFactory.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/DelegatingFieldAccessorFactory.java
@@ -119,11 +119,11 @@ public abstract class DelegatingFieldAccessorFactory implements FieldAccessor
- private final Map, FieldAccessorFactoryProviders> acessorFactoryProviderCache = new HashMap, FieldAccessorFactoryProviders>();
+ private final Map, FieldAccessorFactoryProviders> accessorFactoryProviderCache = new HashMap, FieldAccessorFactoryProviders>();
public FieldAccessorFactoryProviders accessorFactoriesFor(final Class type) {
synchronized (this) {
- final FieldAccessorFactoryProviders fieldAccessorFactoryProviders = acessorFactoryProviderCache.get(type);
+ final FieldAccessorFactoryProviders fieldAccessorFactoryProviders = accessorFactoryProviderCache.get(type);
if (fieldAccessorFactoryProviders != null) return fieldAccessorFactoryProviders;
final FieldAccessorFactoryProviders newFieldAccessorFactories = new FieldAccessorFactoryProviders(type);
ReflectionUtils.doWithFields(type, new ReflectionUtils.FieldCallback() {
@@ -133,7 +133,7 @@ public abstract class DelegatingFieldAccessorFactory implements FieldAccessor
newFieldAccessorFactories.add(field, factory, listenerFactories);
}
});
- acessorFactoryProviderCache.put(type, newFieldAccessorFactories);
+ accessorFactoryProviderCache.put(type, newFieldAccessorFactories);
return newFieldAccessorFactories;
}
}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/IndexingPropertyFieldAccessorListenerFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/IndexingPropertyFieldAccessorListenerFactory.java
index 85e075b65..a13d689be 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/IndexingPropertyFieldAccessorListenerFactory.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/IndexingPropertyFieldAccessorListenerFactory.java
@@ -20,7 +20,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.graphdb.index.Index;
-import org.neo4j.index.impl.lucene.ValueContext;
+import org.neo4j.index.lucene.ValueContext;
import org.springframework.data.annotation.Indexed;
import org.springframework.data.graph.annotation.NodeEntity;
import org.springframework.data.graph.core.GraphBacked;
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/NodeEntityState.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/NodeEntityState.java
index 4f32951ac..bbd5ee7e5 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/NodeEntityState.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/NodeEntityState.java
@@ -21,7 +21,7 @@ import org.neo4j.graphdb.NotInTransactionException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.data.graph.core.NodeBacked;
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
-import org.springframework.persistence.support.StateProvider;
+import org.springframework.data.persistence.StateProvider;
/**
* @author Michael Hunger
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/NodeRelationshipFieldAccessorFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/NodeRelationshipFieldAccessorFactory.java
index 825cc9ce8..6955d2f39 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/NodeRelationshipFieldAccessorFactory.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/NodeRelationshipFieldAccessorFactory.java
@@ -18,6 +18,7 @@ package org.springframework.data.graph.neo4j.fieldaccess;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.DynamicRelationshipType;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.graph.annotation.RelatedTo;
import org.springframework.data.graph.core.NodeBacked;
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
@@ -58,12 +59,21 @@ abstract class NodeRelationshipFieldAccessorFactory implements FieldAccessorFact
return DynamicRelationshipType.withName(relAnnotation.type());
}
+ protected DynamicRelationshipType typeFrom(Field field, RelatedTo relAnnotation) {
+ return "".equals(relAnnotation.type()) ? typeFrom(field) : typeFrom(relAnnotation);
+ }
+
protected RelatedTo getRelationshipAnnotation(Field field) {
return field.getAnnotation(RelatedTo.class);
}
protected boolean hasValidRelationshipAnnotation(Field field) {
final RelatedTo relAnnotation = getRelationshipAnnotation(field);
- return relAnnotation != null && !relAnnotation.elementClass().equals(NodeBacked.class);
+ if (relAnnotation == null) return false;
+ boolean hasElementClass = !relAnnotation.elementClass().equals(NodeBacked.class);
+ if (!hasElementClass) throw new InvalidDataAccessApiUsageException(String.format(
+ "Missing mandatory attribute @RelatedTo.elementClass for one-to-N relationship field %s in class: %s",
+ field.getName(), field.getDeclaringClass().getName()));
+ return true;
}
}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/OneToNRelationshipEntityFieldAccessorFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/OneToNRelationshipEntityFieldAccessorFactory.java
index 1f6d6c50c..96552a528 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/OneToNRelationshipEntityFieldAccessorFactory.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/OneToNRelationshipEntityFieldAccessorFactory.java
@@ -50,9 +50,15 @@ public class OneToNRelationshipEntityFieldAccessorFactory implements FieldAccess
return new OneToNRelationshipEntityFieldAccessor(typeFrom(relEntityAnnotation), dirFrom(relEntityAnnotation), targetFrom(relEntityAnnotation), graphDatabaseContext);
}
- private boolean hasValidRelationshipAnnotation(final Field f) {
- final RelatedToVia relEntityAnnotation = getRelationshipAnnotation(f);
- return relEntityAnnotation != null && !RelationshipBacked.class.equals(relEntityAnnotation.elementClass());
+ private boolean hasValidRelationshipAnnotation(final Field field) {
+ final RelatedToVia relEntityAnnotation = getRelationshipAnnotation(field);
+ if (relEntityAnnotation == null) return false;
+ Class extends RelationshipBacked> elementClass = relEntityAnnotation.elementClass();
+ boolean hasElementClass = elementClass != null && !RelationshipBacked.class.equals(elementClass);
+ if (!hasElementClass) throw new InvalidDataAccessApiUsageException(String.format(
+ "Missing mandatory attribute @RelatedTo.elementClass for one-to-N relationship field %s in class: %s",
+ field.getName(), field.getDeclaringClass().getName()));
+ return hasElementClass;
}
private RelatedToVia getRelationshipAnnotation(final Field field) {
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/OneToNRelationshipFieldAccessorFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/OneToNRelationshipFieldAccessorFactory.java
index 94b274c34..f085d7b19 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/OneToNRelationshipFieldAccessorFactory.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/OneToNRelationshipFieldAccessorFactory.java
@@ -44,7 +44,7 @@ public class OneToNRelationshipFieldAccessorFactory extends NodeRelationshipFiel
@Override
public FieldAccessor forField(final Field field) {
final RelatedTo relAnnotation = getRelationshipAnnotation(field);
- return new OneToNRelationshipFieldAccessor(typeFrom(relAnnotation), dirFrom(relAnnotation), targetFrom(relAnnotation), graphDatabaseContext);
+ return new OneToNRelationshipFieldAccessor(typeFrom(field, relAnnotation), dirFrom(relAnnotation), targetFrom(relAnnotation), graphDatabaseContext);
}
public static class OneToNRelationshipFieldAccessor extends NodeToNodesRelationshipFieldAccessor {
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/PartialNodeEntityState.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/PartialNodeEntityState.java
index bb680595e..424f2400a 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/PartialNodeEntityState.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/PartialNodeEntityState.java
@@ -26,7 +26,7 @@ import org.springframework.data.graph.annotation.RelatedTo;
import org.springframework.data.graph.core.NodeBacked;
import org.springframework.data.graph.neo4j.finder.FinderFactory;
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
-import org.springframework.persistence.support.StateProvider;
+import org.springframework.data.persistence.StateProvider;
import javax.persistence.Id;
import java.lang.reflect.Field;
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/ReadOnlyOneToNRelationshipFieldAccessorFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/ReadOnlyOneToNRelationshipFieldAccessorFactory.java
index 70e3c1ace..8c4379108 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/ReadOnlyOneToNRelationshipFieldAccessorFactory.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/ReadOnlyOneToNRelationshipFieldAccessorFactory.java
@@ -39,7 +39,7 @@ public class ReadOnlyOneToNRelationshipFieldAccessorFactory extends NodeRelation
@Override
public FieldAccessor forField(final Field field) {
final RelatedTo relAnnotation = getRelationshipAnnotation(field);
- return new ReadOnlyOneToNRelationshipFieldAccessor(typeFrom(relAnnotation), dirFrom(relAnnotation), targetFrom(relAnnotation), graphDatabaseContext);
+ return new ReadOnlyOneToNRelationshipFieldAccessor(typeFrom(field, relAnnotation), dirFrom(relAnnotation), targetFrom(relAnnotation), graphDatabaseContext);
}
public static class ReadOnlyOneToNRelationshipFieldAccessor extends OneToNRelationshipFieldAccessorFactory.OneToNRelationshipFieldAccessor {
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/SingleRelationshipFieldAccessorFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/SingleRelationshipFieldAccessorFactory.java
index 54ae107bd..7d97b2565 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/SingleRelationshipFieldAccessorFactory.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/SingleRelationshipFieldAccessorFactory.java
@@ -24,7 +24,6 @@ import org.springframework.data.graph.core.NodeBacked;
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
import java.lang.reflect.Field;
-import java.util.Collection;
import java.util.Collections;
import java.util.Set;
@@ -46,7 +45,7 @@ public class SingleRelationshipFieldAccessorFactory extends NodeRelationshipFiel
final RelatedTo relAnnotation = getRelationshipAnnotation(field);
if (relAnnotation == null)
return new SingleRelationshipFieldAccessor(typeFrom(field), Direction.OUTGOING, targetFrom(field), graphDatabaseContext);
- return new SingleRelationshipFieldAccessor(typeFrom(relAnnotation), dirFrom(relAnnotation), targetFrom(field), graphDatabaseContext);
+ return new SingleRelationshipFieldAccessor(typeFrom(field, relAnnotation), dirFrom(relAnnotation), targetFrom(field), graphDatabaseContext);
}
public static class SingleRelationshipFieldAccessor extends NodeToNodesRelationshipFieldAccessor {
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/finder/AbstractFinder.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/finder/AbstractFinder.java
index 924b351c7..90bd5fe9d 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/finder/AbstractFinder.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/finder/AbstractFinder.java
@@ -6,7 +6,6 @@ import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.index.IndexHits;
import org.neo4j.helpers.collection.IterableWrapper;
-import org.neo4j.index.impl.lucene.ValueContext;
import org.springframework.data.graph.core.GraphBacked;
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/server/ProvidedClassPathXmlApplicationContext.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/server/ProvidedClassPathXmlApplicationContext.java
new file mode 100644
index 000000000..e44496e98
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/server/ProvidedClassPathXmlApplicationContext.java
@@ -0,0 +1,29 @@
+package org.springframework.data.graph.neo4j.server;
+
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * Context that merges the provided graph database service with the given context locations,
+ * so that spring beans that consume a graph database are populated properly.
+ */
+public class ProvidedClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {
+
+ private final GraphDatabaseService database;
+
+ public ProvidedClassPathXmlApplicationContext(GraphDatabaseService database, final String[] locations)
+ throws org.springframework.beans.BeansException {
+ super();
+ setConfigLocations(locations);
+ this.database = database;
+ refresh();
+ }
+
+ @Override
+ protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
+ super.prepareBeanFactory(beanFactory);
+ beanFactory.registerResolvableDependency(GraphDatabaseService.class, database);
+ beanFactory.registerSingleton("graphDatabaseService", database);
+ }
+}
\ No newline at end of file
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/server/SpringPluginInitializer.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/server/SpringPluginInitializer.java
new file mode 100644
index 000000000..c67195855
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/server/SpringPluginInitializer.java
@@ -0,0 +1,84 @@
+package org.springframework.data.graph.neo4j.server;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.beanutils.BeanFactory;
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.server.plugins.PluginLifecycle;
+import org.neo4j.server.plugins.Injectable;
+import org.springframework.context.ApplicationContext;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Initializer to run Spring Data Graph based Server Plugins in a Neo4j REST-server. It takes the list of
+ * config locations and a number of spring beans from those contexts that should be exposed
+ * as injectable dependencies with a Jersey @Context.
+ * For example:
+ *
+ * class MyInitializer extends SpringPluginInitializer {
+ * public MyInitializer() {
+ * super(new String[]{"myContext.xml"},"finderFactory","myRepository");
+ * }
+ * }
+ *
+ */
+public abstract class SpringPluginInitializer implements PluginLifecycle {
+ private String[] contextLocations;
+ private String[] exposedBeans;
+ protected ProvidedClassPathXmlApplicationContext ctx;
+
+ public SpringPluginInitializer(String[] contextLocations, String... exposedBeans) {
+ this.contextLocations = contextLocations;
+ this.exposedBeans = exposedBeans;
+ }
+
+ /**
+ * Binds the provided graph database to the spring contexts so that spring beans that consume a
+ * graph database can be populated.
+ * @param graphDatabaseService of the Neo4j server
+ * @param config of the Neo4j Server
+ * @return Exposes the requested Spring beans as @{see Injectable}s
+ */
+ @Override
+ public Collection> start(GraphDatabaseService graphDatabaseService, Configuration config) {
+ ctx = new ProvidedClassPathXmlApplicationContext(graphDatabaseService, contextLocations);
+ Collection> result = new ArrayList>(exposedBeans.length);
+ for (final String exposedBean : exposedBeans) {
+ result.add(new SpringBeanInjectable(SpringPluginInitializer.this.ctx, exposedBean));
+ }
+ return result;
+ }
+
+ /**
+ * closes the spring context
+ */
+ public void stop() {
+ if (ctx!=null) {
+ ctx.close();
+ }
+ }
+
+ /**
+ * provides access to the Spring bean, proxying the @{see Injectable}
+ * @param optional type of the bean
+ */
+ private static class SpringBeanInjectable implements Injectable {
+ private final String exposedBean;
+ protected ApplicationContext ctx;
+
+ public SpringBeanInjectable(final ApplicationContext ctx, String exposedBean) {
+ this.exposedBean = exposedBean;
+ this.ctx = ctx;
+ }
+
+ public T getValue() {
+ return (T) ctx.getBean(exposedBean);
+
+ }
+
+ public Class getType() {
+ return (Class) ctx.getType(exposedBean);
+ }
+ }
+}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/GraphDatabaseContext.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/GraphDatabaseContext.java
index adfc42d67..ac24b6925 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/GraphDatabaseContext.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/GraphDatabaseContext.java
@@ -29,7 +29,7 @@ import org.springframework.data.graph.core.GraphBacked;
import org.springframework.data.graph.core.NodeBacked;
import org.springframework.data.graph.core.NodeTypeStrategy;
import org.springframework.data.graph.core.RelationshipBacked;
-import org.springframework.persistence.support.EntityInstantiator;
+import org.springframework.data.persistence.EntityInstantiator;
import javax.transaction.Status;
import javax.transaction.SystemException;
@@ -269,28 +269,6 @@ public class GraphDatabaseContext {
}
- /**
- * @param relType
- * @return
- */
- public Node getOrCreateSubReferenceNode(final RelationshipType relType) {
- return getOrCreateSingleOtherNode(graphDatabaseService.getReferenceNode(), relType, Direction.OUTGOING);
- }
-
- private Node getOrCreateSingleOtherNode(Node fromNode, RelationshipType type,
- Direction direction) {
- Relationship singleRelationship = fromNode.getSingleRelationship(type, direction);
- if (singleRelationship != null) {
- return singleRelationship.getOtherNode(fromNode);
- }
-
- Node otherNode = graphDatabaseService.createNode();
- fromNode.createRelationshipTo(otherNode, type);
- return otherNode;
-
- }
-
-
/**
* @return Neo4j Transaction manager
*/
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategy.java
index 671d30bce..2978c0203 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategy.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategy.java
@@ -11,11 +11,14 @@ import org.neo4j.helpers.collection.IterableWrapper;
import org.springframework.data.graph.annotation.NodeEntity;
import org.springframework.data.graph.core.NodeBacked;
import org.springframework.data.graph.core.NodeTypeStrategy;
-import org.springframework.persistence.support.EntityInstantiator;
+import org.springframework.data.persistence.EntityInstantiator;
public class IndexingNodeTypeStrategy implements NodeTypeStrategy {
- private EntityInstantiator graphEntityInstantiator;
+ public static final String NODE_INDEX_NAME = "__types__";
+ public static final String TYPE_PROPERTY_NAME = "__type__";
+ public static final String INDEX_KEY = "className";
+ private EntityInstantiator graphEntityInstantiator;
private GraphDatabaseService graphDb;
public IndexingNodeTypeStrategy(GraphDatabaseService graphDb, EntityInstantiator graphEntityInstantiator) {
@@ -24,7 +27,7 @@ public class IndexingNodeTypeStrategy implements NodeTypeStrategy {
}
private Index getTypesIndex() {
- return graphDb.index().forNodes("__types__");
+ return graphDb.index().forNodes(NODE_INDEX_NAME);
}
@Override
@@ -32,20 +35,20 @@ public class IndexingNodeTypeStrategy implements NodeTypeStrategy {
Node node = entity.getPersistentState();
Class extends NodeBacked> entityClass = entity.getClass();
addToTypesIndex(node, entityClass);
- node.setProperty("__type__", entityClass.getName());
+ node.setProperty(TYPE_PROPERTY_NAME, entityClass.getName());
}
private void addToTypesIndex(Node node, Class extends NodeBacked> entityClass) {
Class> klass = entityClass;
while (klass.getAnnotation(NodeEntity.class) != null) {
- getTypesIndex().add(node, "className", klass.getName());
+ getTypesIndex().add(node, INDEX_KEY, klass.getName());
klass = klass.getSuperclass();
}
}
@Override
public Iterable findAll(Class clazz) {
- final IndexHits allEntitiesOfType = getTypesIndex().get("className", clazz.getName());
+ final IndexHits allEntitiesOfType = getTypesIndex().get(INDEX_KEY, clazz.getName());
return new FilteringIterable(new IterableWrapper(allEntitiesOfType) {
@Override
@SuppressWarnings("unchecked")
@@ -64,7 +67,11 @@ public class IndexingNodeTypeStrategy implements NodeTypeStrategy {
@Override
public long count(Class extends NodeBacked> entityClass) {
- return getTypesIndex().get("className", entityClass.getName()).size();
+ long count = 0;
+ for (Node node : getTypesIndex().get(INDEX_KEY, entityClass.getName())) {
+ count += 1;
+ }
+ return count;
}
@Override
@@ -72,7 +79,7 @@ public class IndexingNodeTypeStrategy implements NodeTypeStrategy {
public Class getJavaType(Node node) {
if (node == null) throw new IllegalArgumentException("Node is null");
try {
- return (Class) Class.forName((String) node.getProperty("__type__"));
+ return (Class) Class.forName((String) node.getProperty(TYPE_PROPERTY_NAME));
} catch (NotFoundException e) {
return null;
} catch (ClassNotFoundException e) {
@@ -82,7 +89,7 @@ public class IndexingNodeTypeStrategy implements NodeTypeStrategy {
@Override
public void preEntityRemoval(NodeBacked entity) {
- getTypesIndex().remove(entity.getPersistentState(), "className", entity.getClass().getName());
+ getTypesIndex().remove(entity.getPersistentState());
}
@Override
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/NodeTypeStrategyFactoryBean.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/NodeTypeStrategyFactoryBean.java
new file mode 100644
index 000000000..e3d97b7b0
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/NodeTypeStrategyFactoryBean.java
@@ -0,0 +1,93 @@
+package org.springframework.data.graph.neo4j.support;
+
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.graphdb.Node;
+import org.neo4j.graphdb.Relationship;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.data.graph.core.NodeBacked;
+import org.springframework.data.graph.core.NodeTypeStrategy;
+import org.springframework.data.persistence.EntityInstantiator;
+
+public class NodeTypeStrategyFactoryBean implements FactoryBean {
+ private GraphDatabaseService graphDatabaseService;
+ private EntityInstantiator graphEntityInstantiator;
+ private Strategy strategy;
+
+ public NodeTypeStrategyFactoryBean(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) {
+ this.graphDatabaseService = graphDatabaseService;
+ this.graphEntityInstantiator = graphEntityInstantiator;
+ strategy = chooseStrategy();
+ }
+
+ private Strategy chooseStrategy() {
+ if (isAlreadyIndexed()) return Strategy.Indexed;
+ if (isAlreadySubRef()) return Strategy.SubRef;
+ return Strategy.Indexed;
+ }
+
+ private boolean isAlreadyIndexed() {
+ return graphDatabaseService.index().existsForNodes(IndexingNodeTypeStrategy.NODE_INDEX_NAME);
+ }
+
+ private boolean isAlreadySubRef() {
+ for (Relationship rel : graphDatabaseService.getReferenceNode().getRelationships()) {
+ if (rel.getType().name().startsWith(SubReferenceNodeTypeStrategy.SUBREF_PREFIX)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public NodeTypeStrategy getObject() throws Exception {
+ return strategy.getObject(graphDatabaseService, graphEntityInstantiator);
+ }
+
+ @Override
+ public Class> getObjectType() {
+ return strategy.getObjectType();
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return false;
+ }
+
+ private enum Strategy {
+ SubRef {
+ @Override
+ NodeTypeStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) {
+ return new SubReferenceNodeTypeStrategy(graphDatabaseService, graphEntityInstantiator);
+ }
+
+ @Override
+ Class extends NodeTypeStrategy> getObjectType() {
+ return SubReferenceNodeTypeStrategy.class;
+ }
+ },
+ Indexed {
+ @Override
+ NodeTypeStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) {
+ return new IndexingNodeTypeStrategy(graphDatabaseService, graphEntityInstantiator);
+ }
+
+ @Override
+ Class extends NodeTypeStrategy> getObjectType() {
+ return IndexingNodeTypeStrategy.class;
+ }
+ },
+ Noop {
+ @Override
+ NodeTypeStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) {
+ return new NoopNodeTypeStrategy();
+ }
+
+ @Override
+ Class extends NodeTypeStrategy> getObjectType() {
+ return NoopNodeTypeStrategy.class;
+ }
+ };
+ abstract NodeTypeStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator);
+ abstract Class extends NodeTypeStrategy> getObjectType();
+ }
+}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategy.java
index 6aa094180..9cfc3728b 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategy.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategy.java
@@ -25,6 +25,7 @@ import org.neo4j.helpers.collection.IterableWrapper;
import org.neo4j.kernel.impl.traversal.TraversalDescriptionImpl;
import org.springframework.data.graph.core.NodeBacked;
import org.springframework.data.graph.core.NodeTypeStrategy;
+import org.springframework.data.persistence.EntityInstantiator;
import java.util.*;
@@ -47,11 +48,13 @@ public class SubReferenceNodeTypeStrategy implements NodeTypeStrategy {
public static final String SUBREF_PREFIX = "SUBREF_";
public static final String SUBREF_CLASS_KEY = "class";
- private final GraphDatabaseContext graphDatabaseContext;
+ private GraphDatabaseService graphDatabaseService;
+ private EntityInstantiator entityInstantiator;
- public SubReferenceNodeTypeStrategy(final GraphDatabaseContext graphDatabaseContext) {
- this.graphDatabaseContext = graphDatabaseContext;
- }
+ public SubReferenceNodeTypeStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator entityInstantiator) {
+ this.graphDatabaseService = graphDatabaseService;
+ this.entityInstantiator = entityInstantiator;
+ }
public static Node getSingleOtherNode(Node node, RelationshipType type,
Direction direction) {
@@ -184,7 +187,7 @@ public class SubReferenceNodeTypeStrategy implements NodeTypeStrategy {
@Override
protected T underlyingObjectToObject(final Relationship rel) {
final Node node = rel.getStartNode();
- T entity = (T) graphDatabaseContext.createEntityFromState(node, getJavaType(node));
+ T entity = (T) entityInstantiator.createEntityFromState(node, getJavaType(node));
if (log.isDebugEnabled()) log.debug("Converting node: " + node + " to entity: " + entity);
return entity;
}
@@ -195,15 +198,33 @@ public class SubReferenceNodeTypeStrategy implements NodeTypeStrategy {
public Node obtainSubreferenceNode(final Class> entityClass) {
- return graphDatabaseContext.getOrCreateSubReferenceNode(subRefRelationshipType(entityClass));
+ return getOrCreateSubReferenceNode(subRefRelationshipType(entityClass));
}
public Node findSubreferenceNode(final Class extends NodeBacked> entityClass) {
- final Relationship subrefRelationship = graphDatabaseContext.getReferenceNode().getSingleRelationship(subRefRelationshipType(entityClass), Direction.OUTGOING);
+ final Relationship subrefRelationship = graphDatabaseService.getReferenceNode().getSingleRelationship(subRefRelationshipType(entityClass), Direction.OUTGOING);
return subrefRelationship != null ? subrefRelationship.getEndNode() : null;
}
private DynamicRelationshipType subRefRelationshipType(Class> clazz) {
return DynamicRelationshipType.withName(SUBREF_PREFIX + clazz.getName());
}
+
+ public Node getOrCreateSubReferenceNode(final RelationshipType relType) {
+ return getOrCreateSingleOtherNode(graphDatabaseService.getReferenceNode(), relType, Direction.OUTGOING);
+ }
+
+ private Node getOrCreateSingleOtherNode(Node fromNode, RelationshipType type,
+ Direction direction) {
+ Relationship singleRelationship = fromNode.getSingleRelationship(type, direction);
+ if (singleRelationship != null) {
+ return singleRelationship.getOtherNode(fromNode);
+ }
+
+ Node otherNode = graphDatabaseService.createNode();
+ fromNode.createRelationshipTo(otherNode, type);
+ return otherNode;
+
+ }
+
}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/node/Neo4jConstructorGraphEntityInstantiator.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/node/Neo4jConstructorGraphEntityInstantiator.java
index ba3e4f421..8212d35a8 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/node/Neo4jConstructorGraphEntityInstantiator.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/node/Neo4jConstructorGraphEntityInstantiator.java
@@ -18,7 +18,7 @@ package org.springframework.data.graph.neo4j.support.node;
import org.neo4j.graphdb.Node;
import org.springframework.data.graph.core.NodeBacked;
-import org.springframework.persistence.support.AbstractConstructorEntityInstantiator;
+import org.springframework.data.persistence.AbstractConstructorEntityInstantiator;
/**
* Implementation of an entity instantiator for neo4j graphdb nodes, binding the entity type to a NodeBacked and the
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/node/PartialNeo4jEntityInstantiator.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/node/PartialNeo4jEntityInstantiator.java
index 3a511de90..59f2409ab 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/node/PartialNeo4jEntityInstantiator.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/node/PartialNeo4jEntityInstantiator.java
@@ -20,7 +20,7 @@ import org.neo4j.graphdb.Node;
import org.springframework.data.graph.core.NodeBacked;
import org.springframework.data.graph.neo4j.fieldaccess.PartialNodeEntityState;
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
-import org.springframework.persistence.support.EntityInstantiator;
+import org.springframework.data.persistence.EntityInstantiator;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/relationship/ConstructorBypassingGraphRelationshipInstantiator.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/relationship/ConstructorBypassingGraphRelationshipInstantiator.java
index 5ef171ee8..e471d4e7b 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/relationship/ConstructorBypassingGraphRelationshipInstantiator.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/relationship/ConstructorBypassingGraphRelationshipInstantiator.java
@@ -20,7 +20,7 @@ import java.lang.reflect.Constructor;
import org.neo4j.graphdb.Relationship;
import org.springframework.data.graph.core.RelationshipBacked;
-import org.springframework.persistence.support.EntityInstantiator;
+import org.springframework.data.persistence.EntityInstantiator;
import sun.reflect.ReflectionFactory;
diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/Group.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/Group.java
index a5511d84b..db7ecadf3 100644
--- a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/Group.java
+++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/Group.java
@@ -26,7 +26,7 @@ public class Group {
public final static String OTHER_NAME_INDEX="other_name";
public static final String SEARCH_GROUPS_INDEX = "search-groups";
- @RelatedTo(type = "persons", direction = Direction.OUTGOING, elementClass = Person.class)
+ @RelatedTo(direction = Direction.OUTGOING, elementClass = Person.class)
private Collection persons;
@RelatedTo(type = "persons", elementClass = Person.class)
diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/InvalidOneToNEntity.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/InvalidOneToNEntity.java
new file mode 100644
index 000000000..5585d7181
--- /dev/null
+++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/InvalidOneToNEntity.java
@@ -0,0 +1,12 @@
+package org.springframework.data.graph.neo4j;
+
+import org.springframework.data.graph.annotation.NodeEntity;
+import org.springframework.data.graph.annotation.RelatedTo;
+
+import java.util.Collection;
+
+@NodeEntity
+public class InvalidOneToNEntity {
+ @RelatedTo
+ private Collection others;
+}
diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/InvalidReadOnlyOneToNEntity.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/InvalidReadOnlyOneToNEntity.java
new file mode 100644
index 000000000..e1b2993dc
--- /dev/null
+++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/InvalidReadOnlyOneToNEntity.java
@@ -0,0 +1,10 @@
+package org.springframework.data.graph.neo4j;
+
+import org.springframework.data.graph.annotation.NodeEntity;
+import org.springframework.data.graph.annotation.RelatedTo;
+
+@NodeEntity
+public class InvalidReadOnlyOneToNEntity {
+ @RelatedTo
+ private Iterable others;
+}
diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/Person.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/Person.java
index b250a2ae2..c7c33ff62 100644
--- a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/Person.java
+++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/Person.java
@@ -44,7 +44,7 @@ public class Person {
private Car car;
- @RelatedTo(type = "mother", direction = Direction.OUTGOING)
+ @RelatedTo
private Person mother;
@RelatedTo(type = "boss", direction = Direction.INCOMING)
diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/config/ConfigurationConfirmationTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/config/ConfigurationConfirmationTest.java
new file mode 100644
index 000000000..99bc799f5
--- /dev/null
+++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/config/ConfigurationConfirmationTest.java
@@ -0,0 +1,16 @@
+package org.springframework.data.graph.neo4j.config;
+
+import org.junit.Test;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * @author mh
+ * @since 23.03.11
+ */
+public class ConfigurationConfirmationTest {
+ @Test(expected = BeanCreationException.class)
+ public void testInvalidTransactionManagerFails() {
+ ClassPathXmlApplicationContext appCtx = new ClassPathXmlApplicationContext("classpath:org/springframework/data/graph/neo4j/config/ConfigurationCofirmationTest-context.xml");
+ }
+}
diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategyTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategyTest.java
index 0353215e3..29b7764e4 100644
--- a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategyTest.java
+++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategyTest.java
@@ -24,11 +24,11 @@ import java.util.HashSet;
import java.util.Set;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml",
"classpath:org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategyOverride-context.xml"})
-@Ignore
public class IndexingNodeTypeStrategyTest {
@Autowired
@@ -57,45 +57,76 @@ public class IndexingNodeTypeStrategyTest {
Index typesIndex = graphDatabaseService.index().forNodes("__types__");
IndexHits thingHits = typesIndex.get("className", thing.getClass().getName());
assertEquals(set(node(thing), node(subThing)), IteratorUtil.addToCollection((Iterable)thingHits, new HashSet()));
+ IndexHits subThingHits = typesIndex.get("className", subThing.getClass().getName());
+ assertEquals(node(subThing), subThingHits.getSingle());
assertEquals(thing.getClass().getName(), node(thing).getProperty("__type__"));
assertEquals(subThing.getClass().getName(), node(subThing).getProperty("__type__"));
}
@Test
- public void testFindAll() throws Exception {
- assertEquals("Did not find all things.",
- Arrays.asList(thing, subThing), IteratorUtil.addToCollection(nodeTypeStrategy.findAll(Thing.class), new ArrayList()));
+ public void testPreEntityRemoval() throws Exception {
+ manualCleanDb();
+ createThings();
+ Index typesIndex = graphDatabaseService.index().forNodes("__types__");
+ IndexHits thingHits;
+ IndexHits subThingHits;
+
+ Transaction tx = graphDatabaseService.beginTx();
+ try
+ {
+ nodeTypeStrategy.preEntityRemoval(thing);
+ tx.success();
+ }
+ finally
+ {
+ tx.finish();
+ }
+
+ thingHits = typesIndex.get("className", thing.getClass().getName());
+ assertEquals(node(subThing), thingHits.getSingle());
+ subThingHits = typesIndex.get("className", subThing.getClass().getName());
+ assertEquals(node(subThing), subThingHits.getSingle());
+
+ tx = graphDatabaseService.beginTx();
+ try
+ {
+ nodeTypeStrategy.preEntityRemoval(subThing);
+ tx.success();
+ }
+ finally
+ {
+ tx.finish();
+ }
+
+ thingHits = typesIndex.get("className", thing.getClass().getName());
+ assertNull(thingHits.getSingle());
+ subThingHits = typesIndex.get("className", subThing.getClass().getName());
+ assertNull(subThingHits.getSingle());
}
@Test
+ @Transactional
+ public void testFindAll() throws Exception {
+ assertEquals("Did not find all things.",
+ Arrays.asList(thing, subThing),
+ IteratorUtil.addToCollection(nodeTypeStrategy.findAll(Thing.class), new ArrayList()));
+ }
+
+ @Test
+ @Transactional
public void testCount() throws Exception {
assertEquals(2, nodeTypeStrategy.count(Thing.class));
}
@Test
+ @Transactional
public void testGetJavaType() throws Exception {
assertEquals(Thing.class, nodeTypeStrategy.getJavaType(node(thing)));
assertEquals(SubThing.class, nodeTypeStrategy.getJavaType(node(subThing)));
}
@Test
- public void testPreEntityRemoval() throws Exception {
- manualCleanDb();
- Transaction tx;
- tx = graphDatabaseService.beginTx();
- try {
- nodeTypeStrategy.preEntityRemoval(thing);
- nodeTypeStrategy.preEntityRemoval(subThing);
- tx.success();
- } finally {
- tx.finish();
- }
- Index typesIndex = graphDatabaseService.index().forNodes("__types__");
- IndexHits thingHits = typesIndex.get("className", thing.getClass().getName());
- assertEquals(0, thingHits.size());
- }
-
- @Test
+ @Transactional
public void testConfirmType() throws Exception {
assertEquals(Thing.class, nodeTypeStrategy.confirmType(node(thing), Thing.class));
assertEquals(SubThing.class, nodeTypeStrategy.confirmType(node(subThing), Thing.class));
diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/NodeEntityRelationshipTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/NodeEntityRelationshipTest.java
index e1b022667..2f77f4bb4 100644
--- a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/NodeEntityRelationshipTest.java
+++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/NodeEntityRelationshipTest.java
@@ -61,7 +61,7 @@ public class NodeEntityRelationshipTest {
Person p = persistedPerson("Michael", 35);
Person mother = persistedPerson("Gabi", 60);
p.setMother(mother);
- Node motherNode = p.getPersistentState().getSingleRelationship(DynamicRelationshipType.withName("mother"), Direction.OUTGOING).getEndNode();
+ Node motherNode = p.getPersistentState().getSingleRelationship(DynamicRelationshipType.withName("Person.mother"), Direction.OUTGOING).getEndNode();
assertEquals(mother.getPersistentState(), motherNode);
assertEquals(mother, p.getMother());
}
diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/PropertyTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/PropertyTest.java
index 6bad30933..917a732cc 100644
--- a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/PropertyTest.java
+++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/PropertyTest.java
@@ -2,19 +2,14 @@ package org.springframework.data.graph.neo4j.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.neo4j.graphdb.NotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.graph.neo4j.Friendship;
-import org.springframework.data.graph.neo4j.Person;
-import static org.springframework.data.graph.neo4j.Person.persistedPerson;
-import org.springframework.data.graph.neo4j.Personality;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.data.graph.neo4j.*;
import org.springframework.data.graph.neo4j.finder.FinderFactory;
import org.springframework.data.graph.neo4j.support.node.Neo4jHelper;
-
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -24,6 +19,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import static org.junit.Assert.assertEquals;
+import static org.springframework.data.graph.neo4j.Person.persistedPerson;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml"})
@@ -131,4 +127,16 @@ public class PropertyTest {
Friendship f = p.knows(p2);
assertEquals("Wrong ID.", (Long)f.getPersistentState().getId(), f.getRelationshipId());
}
+
+ @Test(expected = InvalidDataAccessApiUsageException.class)
+ @Transactional
+ public void testFailFastOnMisconfiguredOneToNProperty() {
+ new InvalidOneToNEntity();
+ }
+
+ @Test(expected = InvalidDataAccessApiUsageException.class)
+ @Transactional
+ public void testFailFastOnMisconfiguredReadOnlyOneToNProperty() {
+ new InvalidReadOnlyOneToNEntity();
+ }
}
diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategyTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategyTest.java
index ad40b5fb0..f9f51585d 100644
--- a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategyTest.java
+++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategyTest.java
@@ -39,7 +39,8 @@ import static org.junit.Assert.assertEquals;
* @since 20.01.11
*/
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = {"classpath:org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml"})
+@ContextConfiguration(locations = {"classpath:org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml",
+ "classpath:org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategyOverride-context.xml"})
public class SubReferenceNodeTypeStrategyTest {
protected final Log log = LogFactory.getLog(getClass());
@@ -48,8 +49,8 @@ public class SubReferenceNodeTypeStrategyTest {
GraphDatabaseContext graphDatabaseContext;
@Autowired
private FinderFactory finderFactory;
-
- private NodeTypeStrategy nodeTypeStrategy;
+ @Autowired
+ private SubReferenceNodeTypeStrategy nodeTypeStrategy;
private Node thingNode;
private Thing thing;
@@ -61,7 +62,6 @@ public class SubReferenceNodeTypeStrategyTest {
@Before
public void setUp() {
- nodeTypeStrategy = graphDatabaseContext.getNodeTypeStrategy();
thingNode = createThing();
}
diff --git a/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/config/ConfigurationCofirmationTest-context.xml b/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/config/ConfigurationCofirmationTest-context.xml
new file mode 100644
index 000000000..149f0f9c0
--- /dev/null
+++ b/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/config/ConfigurationCofirmationTest-context.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/partial/Neo4jGraphRecommendationTest-context.xml b/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/partial/Neo4jGraphRecommendationTest-context.xml
index 3f0482541..2a444b96d 100644
--- a/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/partial/Neo4jGraphRecommendationTest-context.xml
+++ b/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/partial/Neo4jGraphRecommendationTest-context.xml
@@ -86,28 +86,30 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml b/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml
index 1e2ea1075..83e78ba9e 100644
--- a/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml
+++ b/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml
@@ -100,8 +100,9 @@
-
-
+
+
+
diff --git a/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategyOverride-context.xml b/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategyOverride-context.xml
new file mode 100644
index 000000000..e2d8e83f7
--- /dev/null
+++ b/spring-data-neo4j/src/test/resources/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategyOverride-context.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/docbkx/reference/programming-model/annotations.xml b/src/docbkx/reference/programming-model/annotations.xml
index 4f42f682c..7b1985e77 100644
--- a/src/docbkx/reference/programming-model/annotations.xml
+++ b/src/docbkx/reference/programming-model/annotations.xml
@@ -7,8 +7,9 @@
annotation.
- Entities with @NodeEntity
- The @NodeEntity annotation is used to declare a POJO entity to be backed by a node in the
+ @NodeEntity: The basic building block
+
+ The @NodeEntity annotation is used to declare a POJO entity to be backed by a node in the
graph store. Simple fields on the entity are mapped by default to properties of the node. Object
references to other NodeEntities (whether single or Collection) are mapped via relationships. If
the annotation parameter useShortNames is set to false, the properties and relationship
@@ -26,47 +27,20 @@ public class Movie {
}
]]>
+
- RelationshipEntities with @RelationshipEntity
- To access the rich data model of graph relationships, POJOs can also be annotated with
- @RelationshipEntity. Relationship entities can't be instantiated directly but are rather accessed via
- node entities, either by @RelatedToVia fields or by the relateTo or
- getRelationshipTo methods.
- Relationship entities may contain fields that are mapped to properties and two special fields that are
- annotated with @StartNode and @EndNode which point to the start and end node entities respectively. These
- fields are treated as read only fields.
-
-
-
-
- Fields with @GraphProperty
- It is not necessary to annotate fields as they are persisted by default; all fields that contain primitive
- values are persisted directly to the graph. All fields
- convertible to String using the Spring conversion services will be stored as a string. Transient fields are
- not persisted.
- This annotation is mainly used for cross-store persistence.
-
-
-
- Fields with @RelatedTo pointing to other NodeEntities
+ @RelatedTo: Connecting NodeEntities
Relationships to other NodeEntities are mapped to graph relationships. Those can either be single
- relationships (1:1) or multiple relationships (1:n). In most cases single relationships to other
+ relationships (1:1) or multiple relationships (1:N). In most cases single relationships to other
node entities don't have to be annotated as Spring Data Graph can extract all necessary information
from the field using reflection. In the case of multiple relationships, the elementClass
parameter of @RelatedTo must be specified because of type erasure. The direction
(default OUTGOING) and type (inferred from field name) parameters of the annotation are
optional.
- Relationships to single node entities are created when setting the field and deleted when setting it to
+
+ Relationships to single node entities are created when setting the field and deleted when setting it to
null. For multi-relationships the field provides a managed collection (Set) that handles addition and
removal of node entities and reflects those in the graph relationships.
@@ -87,9 +61,33 @@ public class Actor {
}
]]>
+
- Fields with @RelatedToVia pointing to RelationshipEntities
- To provide easy programmatic access to the richer relationship entities of the data model a different
+ @RelationshipEntity: Rich relationships
+
+ To access the full data model of graph relationships, POJOs can also be annotated with
+ @RelationshipEntity. Relationship entities can't be instantiated directly but are rather accessed via
+ node entities, either by @RelatedToVia fields or by the relateTo or
+ getRelationshipTo methods.
+ Relationship entities may contain fields that are mapped to properties and two special fields that are
+ annotated with @StartNode and @EndNode which point to the start and end node entities respectively. These
+ fields are treated as read only fields.
+
+
+
+
+
+ @RelatedToVia: Connecting NodeEntitites via RelationshipEntities
+
+ To provide easy programmatic access to the richer relationship entities of the data model a different
annotation @RelatedToVia can be declared on fields of Iterables of the relationship entity type. These
Iterables then provide read only access to instances of the entity that backs the relationship of this
relationship type. Those instances are initialized with the properties of the relationship and the start
@@ -104,15 +102,16 @@ public class Actor {
]]>
- @StartNode
+ @StartNode: Starting NodeEntity of RelationshipEntity
Annotation for the start node of a relationship entity, read only.
- @EndNode
+ @EndNode: Ending NodeEntity of RelationshipEntity
Annotation for the end node of a relationship entity, read only.
+
- @Indexed
+ @Indexed: Making entities searchable by field value
The @Indexed annotation can be declared on fields that are intended to be indexed by the Neo4j
IndexManager, triggered by value modification.
The resulting index can be used to later retrieve nodes or relationships that contain a certain property
@@ -128,6 +127,7 @@ public class Actor {
it defaults to the one configured with Neo4j ("node" and "relationship").
+
@GraphTraversal
The @GraphTraversal annotation leverages the delegation infrastructure used by the Spring Data Graph
@@ -138,4 +138,15 @@ public class Actor {
elementClass attribute.
+
+
+ @GraphProperty: Cross-store persisted fields
+ It is not necessary to annotate fields as they are persisted by default; all fields that contain primitive
+ values are persisted directly to the graph. All fields
+ convertible to String using the Spring conversion services will be stored as a string. Transient fields are
+ not persisted.
+ This annotation is mainly used for cross-store persistence.
+
+
+
\ No newline at end of file
diff --git a/src/docbkx/reference/programming-model/nodetypestrategy.xml b/src/docbkx/reference/programming-model/nodetypestrategy.xml
index fb93dd6d6..796f5d763 100644
--- a/src/docbkx/reference/programming-model/nodetypestrategy.xml
+++ b/src/docbkx/reference/programming-model/nodetypestrategy.xml
@@ -4,20 +4,45 @@
Reified types for entities
There are several ways to represent the Java type hierarchy of the data model in the graph. In general for all
- node and relationship entities type information is needed to perform certain repository operations. That's
- why the hierarchy up to java.lang.Object of all these classes will be persisted in the graph.
- Implementations of NodeTypeStrategy take care of persisting this information on entity instance
+ node and relationship entities type information is needed to perform certain repository operations. Some of
+ this type information is saved in the graph database.
+
+
+ Implementations of NodeTypeStrategy take care of persisting this information on entity instance
creation. They also provide the repository methods that use this type information to perform their operations
- like findAll, count etc.
+ like findAll, count, etc.
- The current implementation uses nodes to represent the Java type hierarchy which are connected via SUBCLASS_OF
- relationships to their superclass nodes and via INSTANCE_OF relationships to the concrete node entity
- instance node.
+ There are three available implementations to choose from.
+
+
+ IndexingNodeTypeStrategy
+
+ Stores entity types in the integrated index. Each entity node gets indexed with its type and
+ any supertypes that are also @NodeEntity-annotated. The special index used for this
+ is called __types__. Additionally, in order to get the type of an entity node, each
+ node has a property __type__ with the type of that entity.
+
+
+
+ SubReferenceNodeTypeStrategy
+
+ Stores entity types in a tree in the graph representing the type hierarchy. Each entity
+ has a INSTANCE_OF relationship to a type node representing that entity's type. The type may or
+ may not have a SUBCLASS_OF relationship to another type node.
+
+
+
+ NoopNodeTypeStrategy
+
+ Does not store any type information, and does hence not support finding by type, counting by type,
+ or retrieving the type of any entity.
+
+
+
- An alternative approach could use indexing operations to perform the same functionality. Or one could skip the
- NodeTypeStrategy altogether if no strict checks on type conformity are needed, which would allow for a much
- more flexible data model.
+ The default implementation is IndexingNodeTypeStrategy for new graphs. If using an existing
+ graph, Spring Data Graph will default to the strategy first used when the graph was created.
\ No newline at end of file
diff --git a/src/docbkx/tutorial/annotations.xml b/src/docbkx/tutorial/annotations.xml
index 3967d3520..59908fe3d 100644
--- a/src/docbkx/tutorial/annotations.xml
+++ b/src/docbkx/tutorial/annotations.xml
@@ -9,7 +9,7 @@
It's time to put this to a test. How can we be assured that a field is persisted to the graph store? There seemed to be two possibilities. First was to get a
GraphDatabaseContext injected and use its getById() method. The other one was a Finder approach. But let's try to keep things simple.
- How can we persist an entity and how to get its id? No idea, so time to hit the documentation again, revealing that there are a bunch of methods introduced to the
+ How can we persist an entity and how to get its id? Looking at the documentation revealed that there are a bunch of methods introduced to the
entities by the aspects. That's not obvious, but we found the two that would help here - entity.persist() and entity.getNodeId().
So our test looked like this.
diff --git a/src/docbkx/tutorial/domain.xml b/src/docbkx/tutorial/domain.xml
index f875b49dc..c53eb01d6 100644
--- a/src/docbkx/tutorial/domain.xml
+++ b/src/docbkx/tutorial/domain.xml
@@ -3,7 +3,7 @@
Setting the Stage - Movies Domain
- The domain model was the next thing we planned to work on. We wanted to sketch it out first before diving into library details. We also looked at the datamodel of core themoviedb data to
+ The domain model was the next thing we planned to work on. We wanted to sketch it out first before diving into library details. We also looked at the datamodel of core themoviedb data to
confirm that it matched our expectations.
@@ -84,8 +83,8 @@
With this setup we were ready for the first spike: creating a simple MovieController showing a static view. Check. Next was the setup for Spring Data Graph.
- We looked at the README at github and then checked it with the manual. Quite a lot of maven setup for aspectj but otherwise not so much to add.
- Time to add a few lines to our spring configuration.
+ We looked at the README at github and then checked it with the manual. Quite a lot of Maven setup for AspectJ but otherwise not so much to add.
+ Time to add a few lines to our Spring configuration.
@@ -129,7 +128,7 @@
- We spun up jetty to see if there were any obvious issues with the config. Check.
+ We spun up Jetty to see if there were any obvious issues with the config. It all seemed to work just fine. Check.
diff --git a/src/docbkx/tutorial/spring-data-graph.xml b/src/docbkx/tutorial/spring-data-graph.xml
index 77c61f4cf..15a61e809 100644
--- a/src/docbkx/tutorial/spring-data-graph.xml
+++ b/src/docbkx/tutorial/spring-data-graph.xml
@@ -1,16 +1,17 @@
-
+x
Conjuring Magic - Spring Data Graph
- But that was the pure graph database. Using this in our domain would pollute my classes with lots of graph
+ That was the pure graph database. Using this in our domain would pollute our classes with lots of graph
database details. We don't want that. Spring Data Graph
- promised to do the heavy lifting for us. So we checked that next. Obviously it heavily depended on aspectj magic.
- So there would be certain behavior that was
- just observable without being visible in our code, but we were going to give it a try.
+ promised to do the heavy lifting for us. So we checked that next.
+
+ Spring Data Graph depends heavily on AspectJ magic. Some parts of our classes would behave differently,
+ but it would not be visible in our code. We were going to give it a try.
- First step was lots of maven configuration.
+ First step was lots of Maven configuration.
@@ -71,7 +72,7 @@
]]>
- The spring configuration was much easier, thanks to a provided namespace.
+ The Spring configuration was much easier, thanks to a provided namespace.