diff --git a/spring-data-neo4j-aspects/pom.xml b/spring-data-neo4j-aspects/pom.xml
index 0227bedf0..b10b490dc 100644
--- a/spring-data-neo4j-aspects/pom.xml
+++ b/spring-data-neo4j-aspects/pom.xml
@@ -33,9 +33,14 @@
+
+ joda-time
+ joda-time
+ true
+
org.springframework.data
- spring-data-commons-core
+ spring-data-commons
org.springframework.data
diff --git a/spring-data-neo4j-cross-store/pom.xml b/spring-data-neo4j-cross-store/pom.xml
index f6cf8d84a..3575ac9a6 100644
--- a/spring-data-neo4j-cross-store/pom.xml
+++ b/spring-data-neo4j-cross-store/pom.xml
@@ -32,9 +32,14 @@
+
+ joda-time
+ joda-time
+ true
+
org.springframework.data
- spring-data-commons-core
+ spring-data-commons
org.springframework.data
diff --git a/spring-data-neo4j-parent/pom.xml b/spring-data-neo4j-parent/pom.xml
index afe762039..d3c275099 100644
--- a/spring-data-neo4j-parent/pom.xml
+++ b/spring-data-neo4j-parent/pom.xml
@@ -124,7 +124,7 @@
1.6.1
3.0.7.RELEASE
3.1.2.RELEASE
- 1.4.0.RELEASE
+ 1.5.0.BUILD-SNAPSHOT
1.8
0.9
1.6.12
@@ -281,9 +281,15 @@
+
+ joda-time
+ joda-time
+ 1.6
+ true
+
org.springframework.data
- spring-data-commons-core
+ spring-data-commons
${data.commons.version}
@@ -752,6 +758,10 @@
spring-libs-milestone
http://repo.springsource.org/libs-milestone
+
+ spring-libs-snapshot
+ http://repo.springsource.org/libs-snapshot
+
tinkerpop-repository
http://tinkerpop.com/maven2
diff --git a/spring-data-neo4j/pom.xml b/spring-data-neo4j/pom.xml
index 7db27e5bb..479b287ad 100644
--- a/spring-data-neo4j/pom.xml
+++ b/spring-data-neo4j/pom.xml
@@ -36,9 +36,14 @@
+
+ joda-time
+ joda-time
+ true
+
org.springframework.data
- spring-data-commons-core
+ spring-data-commons
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/annotation/GraphId.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/annotation/GraphId.java
index 1059d44b9..34939598a 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/annotation/GraphId.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/annotation/GraphId.java
@@ -16,6 +16,8 @@
package org.springframework.data.neo4j.annotation;
+import org.springframework.data.annotation.Id;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -26,5 +28,6 @@ import java.lang.annotation.Target;
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
+@Id
public @interface GraphId {
}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/DataGraphBeanDefinitionParser.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/DataGraphBeanDefinitionParser.java
index cf9e45b12..85f3aea43 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/DataGraphBeanDefinitionParser.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/DataGraphBeanDefinitionParser.java
@@ -29,6 +29,8 @@ import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.annotation.RelationshipEntity;
+import org.springframework.data.repository.config.RepositoryBeanDefinitionParser;
+import org.springframework.data.repository.config.RepositoryConfigurationExtension;
import org.springframework.util.ClassUtils;
import org.w3c.dom.Element;
@@ -43,6 +45,7 @@ public class DataGraphBeanDefinitionParser extends AbstractBeanDefinitionParser
public static final String ASPECTJ_CONFIG = "org.springframework.data.neo4j.aspects.config.Neo4jAspectConfiguration";
public static final String CROSS_STORE_CONFIG = "org.springframework.data.neo4j.cross_store.config.CrossStoreNeo4jConfiguration";
+
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext context) {
BeanDefinitionBuilder configBuilder = createConfigurationBeanDefinition(element);
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jAuditingBeanDefinitionParser.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jAuditingBeanDefinitionParser.java
new file mode 100644
index 000000000..8c6c0c855
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jAuditingBeanDefinitionParser.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright 2011 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.data.neo4j.config;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.data.config.BeanComponentDefinitionBuilder;
+import org.springframework.data.config.IsNewAwareAuditingHandlerBeanDefinitionParser;
+import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
+import org.springframework.data.neo4j.lifecycle.AuditingEventListener;
+import org.springframework.util.StringUtils;
+import org.w3c.dom.Element;
+
+/**
+ * {@link BeanDefinitionParser} to register a {@link AuditingEventListener} to transparently set auditing information on
+ * an entity.
+ *
+ * @author Oliver Gierke
+ */
+public class Neo4jAuditingBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
+
+ @Override
+ protected Class> getBeanClass(Element element) {
+ return AuditingEventListener.class;
+ }
+
+ @Override
+ protected boolean shouldGenerateId() {
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
+ */
+ @Override
+ protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
+
+ BeanDefinitionRegistry registry = parserContext.getRegistry();
+
+ if (!registry.containsBeanDefinition(IS_NEW_STRATEGY_FACTORY)) {
+
+ String templateName = MAPPING_CONTEXT;
+
+ if (!registry.containsBeanDefinition(MAPPING_CONTEXT)) {
+ templateName = resolveMappingContextRef(element);
+ }
+
+ createIsNewStrategyFactoryBeanDefinition(templateName, parserContext, element);
+ }
+
+ BeanDefinitionParser parser = new IsNewAwareAuditingHandlerBeanDefinitionParser(IS_NEW_STRATEGY_FACTORY);
+ BeanDefinition handlerBeanDefinition = parser.parse(element, parserContext);
+
+ builder.addConstructorArgValue(handlerBeanDefinition);
+ }
+
+ static String resolveMappingContextRef(Element element) {
+
+ String ctxRef = element.getAttribute("mapping-context-ref");
+
+ if (StringUtils.hasText(ctxRef)) {
+ return ctxRef;
+ }
+
+ return "neo4jMappingContext";
+ }
+
+ private String createIsNewStrategyFactoryBeanDefinition(String mappingContextRef, ParserContext context,
+ Element element) {
+
+ BeanDefinitionBuilder mappingContextStrategyFactoryBuilder = BeanDefinitionBuilder
+ .rootBeanDefinition(MappingContextIsNewStrategyFactory.class);
+ mappingContextStrategyFactoryBuilder.addConstructorArgReference(mappingContextRef);
+ BeanComponentDefinitionBuilder builder = new BeanComponentDefinitionBuilder(element, context);
+ context.registerBeanComponent(builder.getComponent(mappingContextStrategyFactoryBuilder, IS_NEW_STRATEGY_FACTORY));
+
+ return IS_NEW_STRATEGY_FACTORY;
+ }
+
+
+ static final String MAPPING_CONTEXT = "neo4jMappingContext";
+ static final String IS_NEW_STRATEGY_FACTORY = "isNewStrategyFactory";
+}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jConfiguration.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jConfiguration.java
index dc1428626..34cc4f8f2 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jConfiguration.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jConfiguration.java
@@ -28,6 +28,7 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.convert.DefaultTypeMapper;
import org.springframework.data.convert.TypeMapper;
+import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
import org.springframework.data.neo4j.core.GraphDatabase;
import org.springframework.data.neo4j.core.TypeRepresentationStrategy;
import org.springframework.data.neo4j.fieldaccess.FieldAccessorFactoryFactory;
@@ -55,6 +56,7 @@ import org.springframework.data.neo4j.support.relationship.RelationshipEntityIns
import org.springframework.data.neo4j.support.relationship.RelationshipEntityStateFactory;
import org.springframework.data.neo4j.support.typerepresentation.ClassValueTypeInformationMapper;
import org.springframework.data.neo4j.support.typerepresentation.TypeRepresentationStrategyFactory;
+import org.springframework.data.support.IsNewStrategyFactory;
import org.springframework.transaction.PlatformTransactionManager;
import javax.validation.Validator;
@@ -114,6 +116,7 @@ public abstract class Neo4jConfiguration {
factoryBean.setTransactionManager(neo4jTransactionManager());
factoryBean.setGraphDatabase(graphDatabase());
+ factoryBean.setIsNewStrategyFactory(isNewStrategyFactory());
factoryBean.setIndexProvider(indexProvider());
@@ -122,6 +125,11 @@ public abstract class Neo4jConfiguration {
}
return factoryBean;
}
+
+ @Bean
+ public IsNewStrategyFactory isNewStrategyFactory() throws Exception {
+ return new MappingContextIsNewStrategyFactory(neo4jMappingContext());
+ }
@Bean
public Neo4jTemplate neo4jTemplate() throws Exception {
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jNamespaceHandler.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jNamespaceHandler.java
new file mode 100644
index 000000000..fe3183338
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jNamespaceHandler.java
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2011 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.data.neo4j.config;
+
+import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+import org.springframework.data.repository.config.RepositoryBeanDefinitionParser;
+import org.springframework.data.repository.config.RepositoryConfigurationExtension;
+
+public class Neo4jNamespaceHandler extends NamespaceHandlerSupport {
+
+ public void init() {
+
+ RepositoryConfigurationExtension extension = new Neo4jRepositoryConfigurationExtension();
+ RepositoryBeanDefinitionParser repositoryBeanDefinitionParser = new RepositoryBeanDefinitionParser(extension);
+
+ registerBeanDefinitionParser("repositories", repositoryBeanDefinitionParser);
+ registerBeanDefinitionParser("config", new DataGraphBeanDefinitionParser());
+ registerBeanDefinitionParser("auditing", new Neo4jAuditingBeanDefinitionParser());
+ }
+}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/lifecycle/AfterSaveEvent.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/lifecycle/AfterSaveEvent.java
index 4e3762708..ecaf7de1f 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/lifecycle/AfterSaveEvent.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/lifecycle/AfterSaveEvent.java
@@ -15,24 +15,8 @@
*/
package org.springframework.data.neo4j.lifecycle;
-import org.springframework.context.ApplicationEvent;
-
-public class AfterSaveEvent extends ApplicationEvent {
- private final T entity;
-
- /**
- * Create a new ApplicationEvent.
- *
- * @param source the component that published the event (never null)
- * @param entity
- */
+public class AfterSaveEvent extends Neo4jLifecycleEvent {
public AfterSaveEvent(Object source, T entity) {
- super(source);
-
- this.entity = entity;
- }
-
- public T getEntity() {
- return entity;
+ super(source, entity);
}
}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/lifecycle/AuditingEventListener.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/lifecycle/AuditingEventListener.java
new file mode 100644
index 000000000..4fc455cef
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/lifecycle/AuditingEventListener.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright 2011 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.data.neo4j.lifecycle;
+
+import org.springframework.context.ApplicationListener;
+import org.springframework.util.Assert;
+
+import org.springframework.data.auditing.AuditingHandler;
+import org.springframework.data.auditing.IsNewAwareAuditingHandler;
+
+/**
+ * Event listener to populate auditing related fields on an entity about to be saved.
+ *
+ * @author Oliver Gierke
+ */
+public class AuditingEventListener implements ApplicationListener> {
+
+ private final IsNewAwareAuditingHandler