diff --git a/pom.xml b/pom.xml
index 7e0279a0b..fec034718 100644
--- a/pom.xml
+++ b/pom.xml
@@ -114,6 +114,11 @@
spring-aspects
${spring.version}
+
+ org.springframework
+ spring-jdbc
+ ${spring.version}
+
org.springframework
spring-tx
@@ -130,6 +135,13 @@
data-commons
1.0.0.CI-SNAPSHOT
+
+
+
+ org.hsqldb
+ hsqldb
+ 1.8.0.10
+
diff --git a/src/main/java/org/springframework/persistence/transaction/NaiveDoubleTransactionManager.java b/src/main/java/org/springframework/persistence/transaction/NaiveDoubleTransactionManager.java
new file mode 100644
index 000000000..653c9e44e
--- /dev/null
+++ b/src/main/java/org/springframework/persistence/transaction/NaiveDoubleTransactionManager.java
@@ -0,0 +1,69 @@
+package org.springframework.persistence.transaction;
+
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.DefaultTransactionStatus;
+
+public class NaiveDoubleTransactionManager implements PlatformTransactionManager {
+
+ private final PlatformTransactionManager a;
+
+ private final PlatformTransactionManager b;
+
+ public NaiveDoubleTransactionManager(PlatformTransactionManager a, PlatformTransactionManager b) {
+ System.err.println("WARNING: Naive JTA/Neo4j Spring transaction manager--must implement properly");
+ this.a = a;
+ this.b = b;
+ }
+
+ @Override
+ public void commit(TransactionStatus ts) throws TransactionException {
+ TransactionStatus tsb = copyTransactionStatus(ts);
+ try {
+ a.commit(ts);
+ }
+ catch (Throwable t) {
+ System.err.println("Continuing to commit tx despite this:" + t);
+ }
+ try {
+ b.commit(tsb);
+ }
+ catch (Throwable t) {
+ System.err.println("Can't commit tx" + t);
+ throw new TransactionException(t.getMessage(), t) {};
+ }
+ }
+
+ private TransactionStatus copyTransactionStatus(TransactionStatus ts) {
+ return new DefaultTransactionStatus(null, ts.isNewTransaction(), false, false, false, null);
+ }
+
+ @Override
+ public TransactionStatus getTransaction(TransactionDefinition td)
+ throws TransactionException {
+ TransactionStatus atx = a.getTransaction(td);
+ TransactionStatus btx = b.getTransaction(td);
+ return atx;
+ }
+
+ @Override
+ public void rollback(TransactionStatus ts) throws TransactionException {
+ TransactionStatus tsb = copyTransactionStatus(ts);
+ try {
+ a.rollback(ts);
+ }
+ catch (Throwable t) {
+ System.err.println("Continuing to rollback tx despite this:" + t);
+ }
+ try {
+ b.rollback(tsb);
+ }
+ catch (Throwable t) {
+ System.err.println("Can't rollback tx" + t);
+ throw new TransactionException(t.getMessage(), t) {};
+ }
+ }
+
+}
diff --git a/src/test/java/org/springframework/persistence/test/Person.java b/src/test/java/org/springframework/persistence/test/Person.java
new file mode 100644
index 000000000..e3e52ba7c
--- /dev/null
+++ b/src/test/java/org/springframework/persistence/test/Person.java
@@ -0,0 +1,34 @@
+package org.springframework.persistence.test;
+
+import org.springframework.persistence.graph.GraphEntity;
+
+@GraphEntity
+public class Person {
+
+ private String name;
+
+ private int age;
+
+ public Person(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+}
diff --git a/src/test/java/org/springframework/persistence/test/graph/Neo4jGraphPersistenceTest.java b/src/test/java/org/springframework/persistence/test/graph/Neo4jGraphPersistenceTest.java
new file mode 100644
index 000000000..9448891e6
--- /dev/null
+++ b/src/test/java/org/springframework/persistence/test/graph/Neo4jGraphPersistenceTest.java
@@ -0,0 +1,38 @@
+package org.springframework.persistence.test.graph;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.persistence.test.Person;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public class Neo4jGraphPersistenceTest {
+
+ @Autowired
+ protected GraphDatabaseService graphDatabaseService;
+
+ @Test
+ public void testGraphDatabaseServiceCreatedAndAutowired() {
+ Assert.assertNotNull( graphDatabaseService );
+ }
+
+ @Test
+ @Transactional
+ @Rollback(false)
+ public void testUserConstructor() {
+ int age = 39;
+ Person p = new Person("Rod", age);
+ Assert.assertEquals(p.getUnderlyingNode().getProperty("Person.name"), p.getName());
+ Assert.assertEquals(age, p.getAge());
+ }
+
+}
diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties
index 035716f13..0d19d218f 100644
--- a/src/test/resources/log4j.properties
+++ b/src/test/resources/log4j.properties
@@ -7,7 +7,7 @@ log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
-log4j.appender.R.File=application.log
+log4j.appender.R.File=target/application.log
log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
diff --git a/src/test/resources/org/springframework/persistence/test/graph/Neo4jGraphPersistenceTest-context.xml b/src/test/resources/org/springframework/persistence/test/graph/Neo4jGraphPersistenceTest-context.xml
new file mode 100644
index 000000000..cd4d53323
--- /dev/null
+++ b/src/test/resources/org/springframework/persistence/test/graph/Neo4jGraphPersistenceTest-context.xml
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+