From 20d103f6cd77e31dcdfdf62131331c3d29236d82 Mon Sep 17 00:00:00 2001 From: Michael Hunger Date: Tue, 26 May 2015 16:19:23 +0200 Subject: [PATCH] DATAGRAPH-643 Upgrade to Neo4j 2.2. * Updated dependency to 2.1.8 and 2.2.2 in a profile "neo22" * Replaced JTA/XA transaction management with an explicit tx-handler * Fixed API and semantic changes * Updated Remote Endpoint to provide means to piggyback index-additions on remote-transaction completion --- pom.xml | 398 +++++++++--------- spring-data-neo4j-aspects/pom.xml | 19 - .../EntityPropertyValidationTests.java | 1 + .../neo4j/aspects/support/FinderTests.java | 22 +- .../support/query/QueryEngineTests.java | 1 + ...aGraphNamespaceHandlerCrossStoreTests.java | 5 +- .../Neo4jGraphRecommendationTests-context.xml | 6 +- spring-data-neo4j-rest/pom.xml | 45 +- .../rest/graphdb/AbstractRemoteDatabase.java | 27 +- .../rest/graphdb/CypherRestGraphDatabase.java | 30 +- .../neo4j/rest/graphdb/RestAPICypherImpl.java | 18 +- .../org/neo4j/rest/graphdb/RestAPIImpl.java | 6 +- .../neo4j/rest/graphdb/RestGraphDatabase.java | 32 +- .../graphdb/transaction/NullTransaction.java | 3 + .../transaction/RemoteCypherTransaction.java | 29 +- .../TransactionFinishListener.java | 10 + .../neo4j/rest/graphdb/LocalTestServer.java | 230 ---------- .../rest/graphdb/MatrixDatabaseTest.java | 7 +- .../graphdb/RestCypherQueryEngineTest.java | 7 +- .../org/neo4j/rest/graphdb/RestIndexTest.java | 5 + .../org/neo4j/rest/graphdb/RestTestBase.java | 52 ++- .../UpdateRelationshipRestApiImplTest.java | 7 + .../rest/graphdb/UpdateRelationshipTest.java | 8 + .../RestEntityPropertyValidationTests.java | 7 +- .../rest/integration/RestFinderTests.java | 8 + .../rest/integration/RestIndexTests.java | 2 +- .../RestNeo4jTemplateApiTests.java | 7 +- .../rest/integration/RestNodeEntityTests.java | 4 +- .../rest/integration/RestProjectionTests.java | 2 +- .../rest/integration/RestPropertyTests.java | 2 +- .../RestRelationshipEntityTests.java | 3 +- .../integration/RestRelationshipTests.java | 2 +- .../integration/RestUniqueEntityTests.java | 2 +- .../neo4j/rest/support/RestEntityTests.java | 3 +- .../rest/support/RestQueryEngineTests.java | 6 +- .../data/neo4j/rest/support/RestTestBase.java | 1 + .../neo4j/rest/support/RestTestHelper.java | 1 + .../support/SpringPluginInitializerTests.java | 1 + .../resources/RestTests-context-index.xml | 10 + .../test/resources/server-test-db.properties | 2 + .../src/test/resources/test-db.properties | 1 + spring-data-neo4j-tx/pom.xml | 19 - .../DefaultSynchronizationManager.java | 40 -- .../neo4j/transaction/JotmFactoryBean.java | 171 -------- .../transaction/MultiTransactionStatus.java | 167 -------- .../neo4j/transaction/SpringProvider.java | 45 -- .../neo4j/transaction/SpringServiceImpl.java | 215 ---------- .../transaction/SynchronizationManager.java | 29 -- .../transaction/JOTMIntegrationTests.java | 145 ------- .../graphdb/ExecutionPlanDescription.java | 98 +++++ .../org/neo4j/graphdb/QueryExecutionType.java | 228 ++++++++++ .../org/neo4j/graphdb/QueryStatistics.java | 114 +++++ .../main/java/org/neo4j/graphdb/Result.java | 181 ++++++++ .../neo4j/config/EnableNeo4jRepositories.java | 6 +- .../JtaTransactionManagerFactoryBean.java | 63 +-- ...gPropertyFieldAccessorListenerFactory.java | 2 + .../repository/GraphRepositoryFactory.java | 10 +- .../support/DelegatingGraphDatabase.java | 10 +- .../support/GraphDatabaseFactoryBean.java | 1 - .../support/Neo4jExceptionTranslator.java | 12 +- .../support/query/CypherQueryEngineImpl.java | 6 + ...tIndexBasedTypeRepresentationStrategy.java | 7 +- .../DataGraphNamespaceHandlerTests.java | 4 +- .../data/neo4j/entity/EntityQueryTests.java | 1 + .../repository/NoIndexDerivedFinderTests.java | 2 +- .../data/neo4j/repository/ReadWriteTests.java | 4 +- .../data/neo4j/support/EntityTestBase.java | 8 +- .../data/neo4j/support/node/Neo4jHelper.java | 10 +- .../neo4j/template/Neo4jTemplateApiTests.java | 7 +- .../Neo4jTemplateApiTransactionTests.java | 4 +- .../data/neo4j/template/NeoApiTests.java | 4 +- spring-data-neo4j/template.mf | 2 + 72 files changed, 1179 insertions(+), 1468 deletions(-) create mode 100644 spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/transaction/TransactionFinishListener.java delete mode 100644 spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/LocalTestServer.java create mode 100644 spring-data-neo4j-rest/src/test/resources/RestTests-context-index.xml delete mode 100644 spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/DefaultSynchronizationManager.java delete mode 100644 spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/JotmFactoryBean.java delete mode 100644 spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/MultiTransactionStatus.java delete mode 100644 spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/SpringProvider.java delete mode 100644 spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/SpringServiceImpl.java delete mode 100644 spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/SynchronizationManager.java delete mode 100644 spring-data-neo4j-tx/src/test/java/org/springframework/data/neo4j/transaction/JOTMIntegrationTests.java create mode 100644 spring-data-neo4j/src/main/java/org/neo4j/graphdb/ExecutionPlanDescription.java create mode 100644 spring-data-neo4j/src/main/java/org/neo4j/graphdb/QueryExecutionType.java create mode 100644 spring-data-neo4j/src/main/java/org/neo4j/graphdb/QueryStatistics.java create mode 100644 spring-data-neo4j/src/main/java/org/neo4j/graphdb/Result.java diff --git a/pom.xml b/pom.xml index 3245d1f3e..bf0ce3213 100644 --- a/pom.xml +++ b/pom.xml @@ -1,228 +1,230 @@ - 4.0.0 + 4.0.0 - org.springframework.data - spring-data-neo4j-parent - 3.4.0.BUILD-SNAPSHOT - pom + org.springframework.data + spring-data-neo4j-parent + 3.4.0.BUILD-SNAPSHOT + pom - Spring Data Neo4j - Parent - Neo4j support for Spring Data - http://www.springsource.org/spring-data/neo4j + Spring Data Neo4j - Parent + Neo4j support for Spring Data + http://www.springsource.org/spring-data/neo4j - - org.springframework.data.build - spring-data-parent - 1.7.0.BUILD-SNAPSHOT - ../spring-data-build/parent/pom.xml - + + org.springframework.data.build + spring-data-parent + 1.7.0.BUILD-SNAPSHOT + ../spring-data-build/parent/pom.xml + - - spring-data-neo4j - spring-data-neo4j-aspects - spring-data-neo4j-cross-store - spring-data-neo4j-tx - spring-data-neo4j-rest - spring-data-neo4j-distribution - + + spring-data-neo4j + spring-data-neo4j-aspects + spring-data-neo4j-cross-store + spring-data-neo4j-tx + spring-data-neo4j-rest + spring-data-neo4j-distribution + - - multi - spring-data-neo4j - 1.11.0.BUILD-SNAPSHOT + + multi + spring-data-neo4j + 1.11.0.BUILD-SNAPSHOT - - 1.7 - 1.7 + + 1.7 + 1.7 - 2.1.7 + 2.1.8 - 0.13-neo4j-2.1.4 - 2.0.1 - + 0.13-neo4j-2.1.6 + 2.0.1 + false + - - - fast - - true - - - - neo22 - - 2.2.0-RC01 - - - - org.neo4j - neo4j-io - ${neo4j.version} - test - test-jar - - - org.neo4j - neo4j-spatial - 0.14-neo4j-2.2.0-M02 - - - - - neo4j-contrib-releases - https://raw.github.com/neo4j-contrib/m2/master/releases - - - + + + fast + + true + + + + neo22 + + 2.2.2 + 0.14-neo4j-2.2.0 + + + + org.neo4j + neo4j-io + ${neo4j.version} + test + test-jar + + + + + neo4j-contrib-releases + https://raw.github.com/neo4j-contrib/m2/master/releases + + + distribute true - - examples - - spring-data-neo4j-examples/hello-worlds + + examples + + spring-data-neo4j-examples/hello-worlds spring-data-neo4j-examples/hello-worlds-aspects - spring-data-neo4j-examples/cineasts - spring-data-neo4j-examples/myrestaurants-social - spring-data-neo4j-examples/todos - spring-data-neo4j-examples/backwardscompatibility - - - + spring-data-neo4j-examples/cineasts + spring-data-neo4j-examples/myrestaurants-social + spring-data-neo4j-examples/todos + spring-data-neo4j-examples/backwardscompatibility + + + - - - mhunger - Michael Hunger - michael.hunger at neotechnology.com - Neo Technology - http://www.neotechnology.com - - Project Lead - - +1 - - - ogierke - Oliver Gierke - ogierke at gopivotal.com - Pivotal - http://www.spring.io - - Developer - - +1 - - - trisberg - Thomas Risberg - trisberg at gopivotal.com - Pivotal - http://www.spring.io - - Developer - - -5 - - - mpollack - Mark Pollack - mpollack at gopivotal.com - Pivotal - http://www.spring.io - - Developer - - -5 - - + + + mhunger + Michael Hunger + michael.hunger at neotechnology.com + Neo Technology + http://www.neotechnology.com + + Project Lead + + +1 + + + ogierke + Oliver Gierke + ogierke at gopivotal.com + Pivotal + http://www.spring.io + + Developer + + +1 + + + trisberg + Thomas Risberg + trisberg at gopivotal.com + Pivotal + http://www.spring.io + + Developer + + -5 + + + mpollack + Mark Pollack + mpollack at gopivotal.com + Pivotal + http://www.spring.io + + Developer + + -5 + + - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.12 - - once - true - false - - **/*Tests.java - - - **/PerformanceTests.java - - - src/test/resources/logging.properties - - - alphabetical - - + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + once + true + false + + **/*Tests.java + + + **/PerformanceTests.java + + + src/test/resources/logging.properties + + + alphabetical + + - - - - - - org.neo4j - neo4j - ${neo4j.version} - - - org.apache.geronimo.specs - geronimo-jta_1.1_spec - 1.1.1 - - - org.neo4j - neo4j-kernel - ${neo4j.version} - test - test-jar - - - - - spring-libs-snapshot - Spring - https://repo.spring.io/libs-snapshot - - - neo4j - http://m2.neo4j.org/content/repositories/releases - - false - - - - geotools - http://download.osgeo.org/webdav/geotools - - false - - - - ow2 - http://repository.ow2.org/nexus/content/repositories/ow2-legacy - - false - - - - + + + + + + org.neo4j + neo4j + ${neo4j.version} + + + javax.transaction + transaction-api + 1.1-rev-1 + + + org.neo4j + neo4j-kernel + ${neo4j.version} + test + test-jar + + + commons-io + commons-io + 1.3.2 + + + + + spring-libs-snapshot + Spring + https://repo.spring.io/libs-snapshot + + + neo4j + http://m2.neo4j.org/content/repositories/releases + + false + + + + geotools + http://download.osgeo.org/webdav/geotools + + false + + + + ow2 + http://repository.ow2.org/nexus/content/repositories/ow2-legacy + + false + + + + spring-plugins-release http://repo.spring.io/plugins-release - + diff --git a/spring-data-neo4j-aspects/pom.xml b/spring-data-neo4j-aspects/pom.xml index 0c8929580..259f9bfce 100644 --- a/spring-data-neo4j-aspects/pom.xml +++ b/spring-data-neo4j-aspects/pom.xml @@ -68,25 +68,6 @@ test - - org.neo4j - neo4j-kernel - ${neo4j.version} - - - org.neo4j - neo4j-lucene-index - ${neo4j.version} - test - - - org.neo4j - neo4j-kernel - ${neo4j.version} - test - test-jar - - org.springframework.data spring-data-neo4j diff --git a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/EntityPropertyValidationTests.java b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/EntityPropertyValidationTests.java index bdd071d71..ba10f43c4 100644 --- a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/EntityPropertyValidationTests.java +++ b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/EntityPropertyValidationTests.java @@ -16,6 +16,7 @@ package org.springframework.data.neo4j.aspects.support; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; diff --git a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/FinderTests.java b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/FinderTests.java index 6bfb449e8..bfdf14dfd 100644 --- a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/FinderTests.java +++ b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/FinderTests.java @@ -32,6 +32,7 @@ import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.transaction.TransactionalTestExecutionListener; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import java.util.*; @@ -131,14 +132,21 @@ public class FinderTests extends EntityTestBase { } @Test - @Transactional + @Transactional(propagation = Propagation.NOT_SUPPORTED ) public void testFindRelationshipEntity() { - Person p1 = persistedPerson("Michael", 35); - Person p2 = persistedPerson("David", 27); - Friendship friendship = p1.knows(p2); - assertEquals("Wrong friendship count.", 1L, (long) friendshipRepository.count()); - assertEquals(friendship, friendshipRepository.findOne(getRelationshipId(friendship))); - assertEquals("Did not find friendship.", Collections.singleton(friendship), new HashSet(IteratorUtil.asCollection(friendshipRepository.findAll()))); + Friendship friendship; + try (Transaction tx = graphDatabaseService.beginTx()) { + Person p1 = persistedPerson("Michael", 35); + Person p2 = persistedPerson("David", 27); + friendship = p1.knows(p2); + tx.success(); + } + try (Transaction tx = graphDatabaseService.beginTx()) { + assertEquals("Wrong friendship count.", 1L, (long) friendshipRepository.count()); + assertEquals(friendship, friendshipRepository.findOne(getRelationshipId(friendship))); + assertEquals("Did not find friendship.", Collections.singleton(friendship), new HashSet(IteratorUtil.asCollection(friendshipRepository.findAll()))); + tx.success(); + } } @Test diff --git a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/query/QueryEngineTests.java b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/query/QueryEngineTests.java index 58b6c6348..f1ff968df 100644 --- a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/query/QueryEngineTests.java +++ b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/query/QueryEngineTests.java @@ -42,6 +42,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; +import org.springframework.test.context.transaction.BeforeTransaction; import org.springframework.test.context.transaction.TransactionalTestExecutionListener; import org.springframework.transaction.annotation.Transactional; diff --git a/spring-data-neo4j-cross-store/src/test/java/org/springframework/data/neo4j/config/DataGraphNamespaceHandlerCrossStoreTests.java b/spring-data-neo4j-cross-store/src/test/java/org/springframework/data/neo4j/config/DataGraphNamespaceHandlerCrossStoreTests.java index 3fe25b1d3..526b882bc 100644 --- a/spring-data-neo4j-cross-store/src/test/java/org/springframework/data/neo4j/config/DataGraphNamespaceHandlerCrossStoreTests.java +++ b/spring-data-neo4j-cross-store/src/test/java/org/springframework/data/neo4j/config/DataGraphNamespaceHandlerCrossStoreTests.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.kernel.EmbeddedGraphDatabase; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.neo4j.support.Neo4jTemplate; import org.springframework.test.context.ContextConfiguration; @@ -43,9 +42,9 @@ public class DataGraphNamespaceHandlerCrossStoreTests { @Test public void injectionForCrossStore() { Assert.assertNotNull("template", template); - EmbeddedGraphDatabase graphDatabaseService = (EmbeddedGraphDatabase) template.getGraphDatabaseService(); + GraphDatabaseService graphDatabaseService = template.getGraphDatabaseService(); String fileSeparator = "target" + System.getProperty("file.separator") + "config-test"; - Assert.assertTrue("store-dir", graphDatabaseService.getStoreDir().endsWith(fileSeparator)); +// Assert.assertTrue("store-dir", graphDatabaseService.getStoreDir().endsWith(fileSeparator)); Assert.assertNotNull("graphDatabaseService", graphDatabaseService); Assert.assertNotNull("transactionManager", transactionManager); } diff --git a/spring-data-neo4j-cross-store/src/test/resources/org/springframework/data/neo4j/partial/Neo4jGraphRecommendationTests-context.xml b/spring-data-neo4j-cross-store/src/test/resources/org/springframework/data/neo4j/partial/Neo4jGraphRecommendationTests-context.xml index 1a9de956d..874e6b87a 100644 --- a/spring-data-neo4j-cross-store/src/test/resources/org/springframework/data/neo4j/partial/Neo4jGraphRecommendationTests-context.xml +++ b/spring-data-neo4j-cross-store/src/test/resources/org/springframework/data/neo4j/partial/Neo4jGraphRecommendationTests-context.xml @@ -21,9 +21,9 @@ - - + + + diff --git a/spring-data-neo4j-rest/pom.xml b/spring-data-neo4j-rest/pom.xml index 114060310..01a19147d 100644 --- a/spring-data-neo4j-rest/pom.xml +++ b/spring-data-neo4j-rest/pom.xml @@ -54,17 +54,6 @@ - - org.neo4j - neo4j-kernel - ${neo4j.version} - - - org.neo4j - neo4j-lucene-index - ${neo4j.version} - - com.mysema.querydsl querydsl-lucene3 @@ -79,14 +68,6 @@ test - - org.neo4j - neo4j-kernel - ${neo4j.version} - test - test-jar - - org.springframework.data spring-data-neo4j @@ -114,6 +95,12 @@ test + + org.neo4j.test + neo4j-harness + ${neo4j.version} + + org.neo4j.app neo4j-server @@ -129,6 +116,26 @@ org.neo4j neo4j + + org.neo4j + neo4j-kernel + + + org.neo4j + neo4j-lucene-index + + + org.neo4j + neo4j-cypher + + + + org.neo4j.app + neo4j-browser + org.mortbay.jetty jetty diff --git a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/AbstractRemoteDatabase.java b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/AbstractRemoteDatabase.java index 9db4c9bc8..c671ac4f7 100644 --- a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/AbstractRemoteDatabase.java +++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/AbstractRemoteDatabase.java @@ -19,29 +19,13 @@ */ package org.neo4j.rest.graphdb; -import org.neo4j.graphdb.*; +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.event.KernelEventHandler; import org.neo4j.graphdb.event.TransactionEventHandler; -import org.neo4j.kernel.GraphDatabaseAPI; -import org.neo4j.kernel.IdGeneratorFactory; -import org.neo4j.kernel.KernelData; -import org.neo4j.kernel.TransactionBuilder; -import org.neo4j.kernel.guard.Guard; -import org.neo4j.kernel.impl.core.KernelPanicEventGenerator; -import org.neo4j.kernel.impl.core.NodeManager; -import org.neo4j.kernel.impl.nioneo.store.StoreId; -import org.neo4j.kernel.impl.persistence.PersistenceSource; -import org.neo4j.kernel.impl.transaction.LockManager; -import org.neo4j.kernel.impl.transaction.XaDataSourceManager; -import org.neo4j.kernel.impl.transaction.xaframework.TxIdGenerator; -import org.neo4j.kernel.impl.util.StringLogger; -import org.neo4j.kernel.info.DiagnosticsManager; import org.neo4j.rest.graphdb.transaction.NullTransaction; -import javax.transaction.TransactionManager; -import java.util.Collection; - -abstract class AbstractRemoteDatabase implements GraphDatabaseAPI { +abstract class AbstractRemoteDatabase implements GraphDatabaseService { public Transaction beginTx() { return new NullTransaction(); } @@ -62,11 +46,6 @@ abstract class AbstractRemoteDatabase implements GraphDatabaseAPI { throw new UnsupportedOperationException(); } - @Override - public TransactionBuilder tx() { - throw new UnsupportedOperationException(); - } - @Override public void shutdown() { } diff --git a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/CypherRestGraphDatabase.java b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/CypherRestGraphDatabase.java index fa03d38c4..41d3e40fc 100644 --- a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/CypherRestGraphDatabase.java +++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/CypherRestGraphDatabase.java @@ -23,7 +23,6 @@ package org.neo4j.rest.graphdb; import org.neo4j.graphdb.*; import org.neo4j.graphdb.schema.Schema; import org.neo4j.graphdb.traversal.BidirectionalTraversalDescription; -import org.neo4j.kernel.impl.nioneo.store.StoreId; import org.neo4j.rest.graphdb.entity.RestNode; import org.neo4j.rest.graphdb.index.RestIndexManager; import org.neo4j.rest.graphdb.query.RestCypherTransactionManager; @@ -82,16 +81,11 @@ public class CypherRestGraphDatabase extends AbstractRemoteDatabase implements R public Relationship getRelationshipById( long id ) { return this.restAPI.getRelationshipById(id); } - @Override + public String getStoreDir() { return restAPI.getBaseUri(); } - @Override - public StoreId storeId() { - return null; - } - @Override public boolean isAvailable(long timeout) { return restAPI!=null; @@ -101,7 +95,6 @@ public class CypherRestGraphDatabase extends AbstractRemoteDatabase implements R return restAPI.getTxManager(); } - @Override public DependencyResolver getDependencyResolver() { return new DependencyResolver.Adapter() { @Override @@ -122,6 +115,7 @@ public class CypherRestGraphDatabase extends AbstractRemoteDatabase implements R try { getTxManager().rollback(); } catch (SystemException|IllegalStateException e) { + e.printStackTrace(); // ignore } restAPI.close(); @@ -166,5 +160,25 @@ public class CypherRestGraphDatabase extends AbstractRemoteDatabase implements R public Collection getAllLabelNames() { return restAPI.getAllLabelNames(); } + + public ResourceIterator findNodes(Label label, String s, Object o) { + return null; + } + + public Node findNode(Label label, String s, Object o) { + return null; + } + + public ResourceIterator findNodes(Label label) { + return null; + } + + public Result execute(String s) { + return null; + } + + public Result execute(String s, Map map) { + return null; + } } diff --git a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestAPICypherImpl.java b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestAPICypherImpl.java index 05063f0db..87b5495ba 100644 --- a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestAPICypherImpl.java +++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestAPICypherImpl.java @@ -34,6 +34,7 @@ import org.neo4j.rest.graphdb.index.IndexInfo; import org.neo4j.rest.graphdb.index.RestIndex; import org.neo4j.rest.graphdb.index.RestIndexManager; import org.neo4j.rest.graphdb.query.*; +import org.neo4j.rest.graphdb.transaction.TransactionFinishListener; import org.neo4j.rest.graphdb.traversal.RestTraversalDescription; import org.neo4j.rest.graphdb.traversal.RestTraverser; import org.neo4j.rest.graphdb.util.QueryResult; @@ -679,8 +680,21 @@ public class RestAPICypherImpl implements RestAPI { @Override - public void addToIndex(T entity, RestIndex index, String key, Object value) { - restAPI.addToIndex(entity, index, key, value); + public void addToIndex(final T entity, final RestIndex index, final String key, final Object value) { + if (!getTxManager().isActive()) { + restAPI.addToIndex(entity, index, key, value); + return; + } + getTxManager().getRemoteCypherTransaction().registerListener(new TransactionFinishListener() { + @Override + public void comitted() { + restAPI.addToIndex(entity, index, key, value); + } + + @Override + public void rolledBack() { + } + }); } @Override diff --git a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestAPIImpl.java b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestAPIImpl.java index 5d12ace1c..ca10e99a4 100644 --- a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestAPIImpl.java +++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestAPIImpl.java @@ -509,7 +509,7 @@ public class RestAPIImpl implements RestAPI { RequestResult response = getRestRequest().with(node.getUri()).post("labels", labels); if (response.statusOtherThan(Status.NO_CONTENT)) { - throw new IllegalStateException("error adding labels, received " + response); + throw new IllegalStateException("error adding labels, received " + response.getText()); } } @@ -700,7 +700,9 @@ public class RestAPIImpl implements RestAPI { } final Map data = map("key", key, "value", value, "uri", uri); final RequestResult result = getRestRequest().post(indexPath(index, null, null), data); - if (result.statusOtherThan(Status.CREATED)) throw new RuntimeException(String.format("Error adding element %d %s %s to index %s", restEntity.getId(), key, value, index.getIndexName())); + if (result.statusOtherThan(Status.CREATED)) { + throw new RuntimeException(String.format("Error adding element %d %s %s to index %s status %s\n%s", restEntity.getId(), key, value, index.getIndexName(), result.getStatus(),result.getText())); + } } @Override diff --git a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestGraphDatabase.java b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestGraphDatabase.java index 018e66848..3714c87c1 100644 --- a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestGraphDatabase.java +++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestGraphDatabase.java @@ -23,7 +23,7 @@ package org.neo4j.rest.graphdb; import org.neo4j.graphdb.*; import org.neo4j.graphdb.schema.Schema; import org.neo4j.graphdb.traversal.BidirectionalTraversalDescription; -import org.neo4j.kernel.impl.nioneo.store.StoreId; +import org.neo4j.helpers.collection.IteratorUtil; import org.neo4j.rest.graphdb.entity.RestNode; import org.neo4j.rest.graphdb.index.RestIndexManager; import org.neo4j.rest.graphdb.query.RestCypherQueryEngine; @@ -35,6 +35,7 @@ import org.neo4j.rest.graphdb.util.ResourceIterableWrapper; import javax.transaction.TransactionManager; import java.util.Collection; import java.util.LinkedHashSet; +import java.util.Map; /** * @deprecated use CypherRestGraphDatabase instead @@ -87,16 +88,11 @@ public class RestGraphDatabase extends AbstractRemoteDatabase implements RestAPI public Relationship getRelationshipById( long id ) { return this.restAPI.getRelationshipById(id); } - @Override + public String getStoreDir() { return restAPI.getBaseUri(); } - @Override - public StoreId storeId() { - return null; - } - @Override public boolean isAvailable(long timeout) { return restAPI!=null; @@ -106,7 +102,6 @@ public class RestGraphDatabase extends AbstractRemoteDatabase implements RestAPI return new NullTransactionManager(); } - @Override public DependencyResolver getDependencyResolver() { return new DependencyResolver.Adapter() { @Override @@ -162,5 +157,26 @@ public class RestGraphDatabase extends AbstractRemoteDatabase implements RestAPI public Collection getAllLabelNames() { return restAPI.getAllLabelNames(); } + + public ResourceIterator findNodes(Label label, String property, Object value) { + return findNodesByLabelAndProperty(label,property,value).iterator(); + } + + public Node findNode(Label label, String property, Object value) { + return IteratorUtil.singleOrNull(findNodesByLabelAndProperty(label,property,value)); + } + + public ResourceIterator findNodes(Label label) { + return null; + } + + public Result execute(String statement) { + return execute(statement,null); + } + + public Result execute(String statement, Map params) { +// return cypherQueryEngine.query(statement,params); + return null; + } } diff --git a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/transaction/NullTransaction.java b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/transaction/NullTransaction.java index 6cd51b5c9..6764dd660 100644 --- a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/transaction/NullTransaction.java +++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/transaction/NullTransaction.java @@ -48,4 +48,7 @@ public class NullTransaction implements Transaction { public Lock acquireReadLock(PropertyContainer propertyContainer) { return null; } + + public void terminate() { + } } diff --git a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/transaction/RemoteCypherTransaction.java b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/transaction/RemoteCypherTransaction.java index e6327c07f..d1fea8c1e 100644 --- a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/transaction/RemoteCypherTransaction.java +++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/transaction/RemoteCypherTransaction.java @@ -24,12 +24,17 @@ import org.neo4j.rest.graphdb.query.CypherTransaction; import javax.transaction.Status; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import static org.neo4j.helpers.collection.MapUtil.map; public class RemoteCypherTransaction implements Transaction { + private final List listeners = new ArrayList<>(); + int status = Status.STATUS_NO_TRANSACTION; boolean success, failure; CypherTransaction tx; @@ -46,6 +51,12 @@ public class RemoteCypherTransaction implements Transaction { '}'; } + public void registerListener(TransactionFinishListener listener) { + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + public RemoteCypherTransaction(CypherTransaction tx) { this.tx = tx; status = Status.STATUS_ACTIVE; @@ -79,16 +90,25 @@ public class RemoteCypherTransaction implements Transaction { status = Status.STATUS_COMMITTED; } else { - tx().rollback(); + if (tx()!=null) tx().rollback(); status = Status.STATUS_ROLLEDBACK; } } finally { tx = null; + notifyFinish(); } } + private void notifyFinish() { + for (TransactionFinishListener listener : listeners) { + if (status == Status.STATUS_COMMITTED) listener.comitted(); + else listener.rolledBack(); + } + listeners.clear(); + } + private CypherTransaction tx() { - if (tx == null) throw new IllegalStateException("No transaction active"); + if (tx == null && !failure) throw new IllegalStateException("No transaction active"); return tx; } @@ -125,4 +145,9 @@ public class RemoteCypherTransaction implements Transaction { public boolean isActive() { return tx != null; } + + public void terminate() { + failure(); + close(); + } } diff --git a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/transaction/TransactionFinishListener.java b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/transaction/TransactionFinishListener.java new file mode 100644 index 000000000..5e352349f --- /dev/null +++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/transaction/TransactionFinishListener.java @@ -0,0 +1,10 @@ +package org.neo4j.rest.graphdb.transaction; + +/** +* @author mh +* @since 20.05.15 +*/ +public interface TransactionFinishListener { + void comitted(); + void rolledBack(); +} diff --git a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/LocalTestServer.java b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/LocalTestServer.java deleted file mode 100644 index 6f483325a..000000000 --- a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/LocalTestServer.java +++ /dev/null @@ -1,230 +0,0 @@ -/** - * Copyright (c) 2002-2013 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.rest.graphdb; - -import org.eclipse.jetty.util.component.LifeCycle; -import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.kernel.GraphDatabaseAPI; -import org.neo4j.kernel.configuration.Config; -import org.neo4j.kernel.logging.Logging; -import org.neo4j.server.CommunityNeoServer; -import org.neo4j.server.configuration.PropertyFileConfigurator; -import org.neo4j.server.database.Database; -import org.neo4j.server.database.WrappedDatabase; -import org.neo4j.server.modules.RESTApiModule; -import org.neo4j.server.modules.ServerModule; -import org.neo4j.server.modules.ThirdPartyJAXRSModule; -import org.neo4j.server.preflight.PreFlightTasks; -import org.neo4j.server.web.Jetty9WebServer; -import org.neo4j.server.web.WebServer; -import org.neo4j.test.TestGraphDatabaseFactory; - -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URL; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import static java.util.Arrays.asList; - -/** - * @author mh - * @since 24.03.11 - */ -public class LocalTestServer { - private CommunityNeoServer neoServer; - private final int port; - private final String hostname; - protected String propertiesFile = "test-db.properties"; - private final GraphDatabaseAPI graphDatabase; - private String userAgent; - - public LocalTestServer() { - this("localhost",7473); - } - - public LocalTestServer(String hostname, int port) { - this.port = port; - this.hostname = hostname; - graphDatabase = (GraphDatabaseAPI) new TestGraphDatabaseFactory().newImpermanentDatabase(); - } - - public void start() { - if (neoServer!=null) throw new IllegalStateException("Server already running"); - URL url = getClass().getResource("/" + propertiesFile); - if (url==null) throw new IllegalArgumentException("Could not resolve properties file "+propertiesFile); - Logging logging = graphDatabase.getDependencyResolver().resolveDependency(Logging.class); - final Jetty9WebServer jettyWebServer = new Jetty9WebServer(logging); /* { - @Override - protected void startJetty() { - final Server jettyServer = getJetty(); - jettyServer.setStopAtShutdown(true); - final JettyStartupListener startupListener = new JettyStartupListener(); - jettyServer.getServer().addLifeCycleListener(startupListener); - // System.err.println("jetty is started before notification " + jettyServer.isStarted()); - - super.startJetty(); - - startupListener.await(); - jettyServer.removeLifeCycleListener(startupListener); - // System.err.println("jetty is started after notification " + jettyServer.isStarted()); - } - @Override - public void stop() { - final Server jettyServer = getJetty(); - final JettyStartupListener listener = new JettyStartupListener(); - jettyServer.getServer().addLifeCycleListener(listener); - - super.stop(); - - listener.await(); - jettyServer.removeLifeCycleListener(listener); - } - }; */ - jettyWebServer.addFilter(new Filter() { - public void init(FilterConfig filterConfig) throws ServletException { } - - public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { - userAgent = ((HttpServletRequest)request).getHeader("User-Agent"); - filterChain.doFilter(request, response); - } - - public void destroy() { } - },"/*"); - neoServer = new CommunityNeoServer(new PropertyFileConfigurator(new File(url.getPath())), new Database.Factory() { - @Override - public Database newDatabase(Config config, Logging logging) { - return new WrappedDatabase(graphDatabase); - } - },logging) { - @Override - protected int getWebServerPort() { - return port; - } - - @Override - protected PreFlightTasks createPreflightTasks() { - return new PreFlightTasks(logging); - } - - @Override - protected WebServer createWebServer() { - return jettyWebServer; - } - - @Override - protected Iterable createServerModules() { - return asList(new RESTApiModule(webServer,database,configurator.configuration(),logging),new ThirdPartyJAXRSModule(webServer,configurator,logging,this)); - } - }; - neoServer.start(); - try { - Thread.sleep(500); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - public void stop() { - try { - neoServer.stop(); - } catch(Exception e) { - System.err.println("Error stopping server: "+e.getMessage()); - } - neoServer=null; - } - - public int getPort() { - return port; - } - - public String getHostname() { - return hostname; - } - - public LocalTestServer withPropertiesFile(String propertiesFile) { - this.propertiesFile = propertiesFile; - return this; - } - public Database getDatabase() { - return neoServer.getDatabase(); - } - - public URI baseUri() { - return neoServer.baseUri(); - } - - public void cleanDb() { - Neo4jDatabaseCleaner cleaner = new Neo4jDatabaseCleaner(getGraphDatabase()); - cleaner.cleanDb(); - } - - public GraphDatabaseService getGraphDatabase() { - return getDatabase().getGraph(); - } - - public String getUserAgent() { - return userAgent; - } - - private static class JettyStartupListener implements LifeCycle.Listener { - CountDownLatch latch=new CountDownLatch(1); - public void await() { - try { - latch.await(5, TimeUnit.SECONDS); - } catch(InterruptedException ie) { - Thread.currentThread().interrupt(); - throw new RuntimeException(ie); - } - } - - @Override - public void lifeCycleStarting(LifeCycle event) { - System.err.println("STARTING"); - } - - @Override - public void lifeCycleStarted(LifeCycle event) { - System.err.println("STARTED"); - latch.countDown(); - } - - @Override - public void lifeCycleFailure(LifeCycle event, Throwable cause) { - System.err.println("FAILURE "+cause.getMessage()); - latch.countDown(); - throw new RuntimeException(cause); - } - - @Override - public void lifeCycleStopping(LifeCycle event) { - System.err.println("STOPPING"); - } - - @Override - public void lifeCycleStopped(LifeCycle event) { - System.err.println("STOPPED"); - latch.countDown(); - } - } -} diff --git a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/MatrixDatabaseTest.java b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/MatrixDatabaseTest.java index 90eedd426..f4ebd1df4 100644 --- a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/MatrixDatabaseTest.java +++ b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/MatrixDatabaseTest.java @@ -32,9 +32,12 @@ import org.neo4j.rest.graphdb.MatrixDataGraph.RelTypes; import org.neo4j.test.ImpermanentGraphDatabase; import org.neo4j.test.TestGraphDatabaseFactory; +import java.util.HashSet; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; - +import static org.neo4j.helpers.collection.IteratorUtil.addToCollection; +import static org.neo4j.helpers.collection.IteratorUtil.asCollection; /** @@ -149,7 +152,7 @@ public class MatrixDatabaseTest { Index goodGuys = index.forNodes("heroes"); IndexHits hits = goodGuys.query( "name", "*" ); Traverser heroesTraverser = getHeroes(); - assertEquals( heroesTraverser.nodes().iterator().next().getId(), hits.iterator().next().getId() ); + assertEquals( addToCollection(heroesTraverser.nodes(), new HashSet()), addToCollection(hits.iterator() , new HashSet())); } diff --git a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestCypherQueryEngineTest.java b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestCypherQueryEngineTest.java index 228199814..9944ba5f7 100644 --- a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestCypherQueryEngineTest.java +++ b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestCypherQueryEngineTest.java @@ -28,6 +28,7 @@ import java.util.Map; import org.junit.Before; import org.junit.Test; +import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Transaction; import org.neo4j.helpers.collection.IteratorUtil; @@ -40,7 +41,11 @@ public class RestCypherQueryEngineTest extends RestTestBase { private RestAPI restAPI; private MatrixDataGraph embeddedMatrixdata; private MatrixDataGraph restMatrixData; - + + protected GraphDatabaseService createRestGraphDatabase() { + return new RestGraphDatabase(SERVER_ROOT_URI); + } + @Before public void init() throws Exception { embeddedMatrixdata = new MatrixDataGraph(getGraphDatabase(),nodeId()).createNodespace(); diff --git a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestIndexTest.java b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestIndexTest.java index e3ef2e231..38b082ee4 100644 --- a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestIndexTest.java +++ b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestIndexTest.java @@ -28,6 +28,7 @@ import org.apache.lucene.index.Term; import org.apache.lucene.search.TermQuery; import org.junit.Assert; import org.junit.Test; +import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.index.Index; @@ -43,6 +44,10 @@ public class RestIndexTest extends RestTestBase { private static final String NODE_INDEX_NAME = "NODE_INDEX"; private static final String REL_INDEX_NAME = "REL_INDEX"; + protected GraphDatabaseService createRestGraphDatabase() { + return new RestGraphDatabase(SERVER_ROOT_URI); + } + @Test public void testAddToNodeIndex() { nodeIndex().add(node(), "name", "test"); diff --git a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestTestBase.java b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestTestBase.java index 03cec090a..73d68a5c2 100644 --- a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestTestBase.java +++ b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/RestTestBase.java @@ -25,11 +25,16 @@ import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.neo4j.graphdb.*; +import org.neo4j.harness.ServerControls; +import org.neo4j.harness.TestServerBuilders; +import org.neo4j.harness.internal.InProcessServerControls; import org.neo4j.helpers.collection.IteratorUtil; import org.neo4j.rest.graphdb.entity.RestNode; import org.neo4j.rest.graphdb.util.Config; +import org.neo4j.server.AbstractNeoServer; import org.neo4j.tooling.GlobalGraphOperations; +import java.lang.reflect.Field; import java.net.URISyntaxException; import java.util.Iterator; @@ -38,28 +43,43 @@ import static org.junit.Assert.assertEquals; public class RestTestBase { private GraphDatabaseService restGraphDb; - private static final String HOSTNAME = "localhost"; - private static final int PORT = 7473; - private static LocalTestServer neoServer; - public static final String SERVER_ROOT = "http://" + HOSTNAME + ":" + PORT; - protected static final String SERVER_ROOT_URI = SERVER_ROOT + "/db/data/"; + private static String HOSTNAME = "localhost"; + private static int PORT = 7473; + private static ServerControls neoServer; + public static String SERVER_ROOT = "http://" + HOSTNAME + ":" + PORT; + protected static String SERVER_ROOT_URI = SERVER_ROOT + "/db/data/"; private long referenceNodeId; private Node referenceNode; + private static AbstractNeoServer server; static { initServer(); } - protected static void initServer() { - if (neoServer!=null) { - neoServer.stop(); + try { + if (neoServer != null) { + neoServer.close(); + } + neoServer = TestServerBuilders.newInProcessBuilder() + .withConfig("dbms.security.auth_enabled", "false") + .withExtension("/test", "org.springframework.data.neo4j.rest.support") + .newServer(); + + Field field = InProcessServerControls.class.getDeclaredField("server"); + field.setAccessible(true); + server = (AbstractNeoServer) field.get(neoServer); + SERVER_ROOT = neoServer.httpURI().toString(); + SERVER_ROOT = SERVER_ROOT.substring(0, SERVER_ROOT.length() - 1); + SERVER_ROOT_URI = SERVER_ROOT + "/db/data/"; + HOSTNAME = neoServer.httpURI().getHost(); + PORT = neoServer.httpURI().getPort(); + } catch (Exception e) { + throw new RuntimeException("Error starting in-process server",e); } - neoServer = new LocalTestServer(HOSTNAME,PORT).withPropertiesFile("server-test-db.properties"); } @BeforeClass public static void startDb() throws Exception { - neoServer.start(); tryConnect(); } @@ -81,7 +101,8 @@ public class RestTestBase { @Before public void setUp() throws Exception { System.setProperty(Config.CONFIG_BATCH_TRANSACTION,"false"); - neoServer.cleanDb(); + new Neo4jDatabaseCleaner(server.getDatabase().getGraph()).cleanDb(); +// server.getDatabase().getGraph().cleanDb(); restGraphDb = createRestGraphDatabase(); GraphDatabaseService db = getGraphDatabase(); @@ -105,8 +126,8 @@ public class RestTestBase { @AfterClass public static void shutdownDb() { - neoServer.stop(); - +// neoServer.close(); +// neoServer = null; } protected Relationship relationship() { @@ -123,7 +144,7 @@ public class RestTestBase { } protected GraphDatabaseService getGraphDatabase() { - return neoServer.getGraphDatabase(); + return server.getDatabase().getGraph(); } protected GraphDatabaseService getRestGraphDb() { @@ -138,6 +159,7 @@ public class RestTestBase { return getGraphDatabase().getNodeById(node.getId()); } public String getUserAgent() { - return neoServer.getUserAgent(); + return null; // todo install filter +// return neoServer.getUserAgent(); } } diff --git a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/UpdateRelationshipRestApiImplTest.java b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/UpdateRelationshipRestApiImplTest.java index 323d120c5..6f89525fc 100644 --- a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/UpdateRelationshipRestApiImplTest.java +++ b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/UpdateRelationshipRestApiImplTest.java @@ -1,6 +1,8 @@ package org.neo4j.rest.graphdb; +import org.junit.Test; import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.rest.graphdb.query.CypherTransactionExecutionException; /** * @author mh @@ -13,4 +15,9 @@ public class UpdateRelationshipRestApiImplTest extends UpdateRelationshipTest { restAPI = new RestAPIImpl(SERVER_ROOT_URI); return new RestGraphDatabase(restAPI); } + + @Test + public void testUpdateRelationshipsRemoveAddNoType() throws Exception { + super.testUpdateRelationshipsRemoveAddNoType(); + } } diff --git a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/UpdateRelationshipTest.java b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/UpdateRelationshipTest.java index 2cd66c341..68318db7a 100644 --- a/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/UpdateRelationshipTest.java +++ b/spring-data-neo4j-rest/src/test/java/org/neo4j/rest/graphdb/UpdateRelationshipTest.java @@ -67,6 +67,13 @@ public class UpdateRelationshipTest extends RestTestBase { updateRelationships(); } + /* + given + (remove)-[:LIKES]->(node) + (node)-[:KNOWS]->(keep) + when update to (node)-->(keep) + then + */ @Test(expected = CypherTransactionExecutionException.class) public void testUpdateRelationshipsRemoveAddNoType() throws Exception { Node node = node(); @@ -74,6 +81,7 @@ public class UpdateRelationshipTest extends RestTestBase { node.createRelationshipTo(keep, KNOWS); type = null; updateTo = asList(keep); + expected = asList(remove, keep); updateRelationships(); } diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestEntityPropertyValidationTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestEntityPropertyValidationTests.java index 5f5c99e35..323cbc9dd 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestEntityPropertyValidationTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestEntityPropertyValidationTests.java @@ -16,10 +16,7 @@ package org.springframework.data.neo4j.rest.integration; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; +import org.junit.*; import org.junit.runner.RunWith; import org.springframework.data.neo4j.aspects.support.EntityPropertyValidationTests; import org.springframework.data.neo4j.rest.support.RestTestBase; @@ -37,7 +34,7 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTests-context.xml", "classpath:RestTests-context.xml"}) -@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class}) + public class RestEntityPropertyValidationTests extends EntityPropertyValidationTests { @BeforeClass diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestFinderTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestFinderTests.java index 92256a127..8af9b3e87 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestFinderTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestFinderTests.java @@ -19,6 +19,7 @@ package org.springframework.data.neo4j.rest.integration; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.data.neo4j.aspects.support.FinderTests; import org.springframework.data.neo4j.rest.support.RestTestBase; @@ -28,6 +29,8 @@ import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.transaction.TransactionalTestExecutionListener; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; /** * @author mh @@ -53,4 +56,9 @@ public class RestFinderTests extends FinderTests { RestTestBase.shutdownDb(); } + @Test + @Transactional(propagation = Propagation.NOT_SUPPORTED) + public void testFindRelationshipEntity() { + super.testFindRelationshipEntity(); + } } diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestIndexTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestIndexTests.java index a5a9ffcc7..63ff9e54c 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestIndexTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestIndexTests.java @@ -43,7 +43,7 @@ import static org.springframework.data.neo4j.aspects.Person.persistedPerson; */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTests-context.xml", - "classpath:RestTests-context.xml"}) + "classpath:RestTests-context-index.xml"}) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) public class RestIndexTests extends IndexTests { diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestNeo4jTemplateApiTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestNeo4jTemplateApiTests.java index 3ce09ee8e..7b1851ee4 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestNeo4jTemplateApiTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestNeo4jTemplateApiTests.java @@ -24,12 +24,16 @@ import org.junit.Ignore; import org.junit.Test; import org.neo4j.graphdb.GraphDatabaseService; import org.springframework.dao.DataAccessException; +import org.springframework.data.neo4j.config.JtaTransactionManagerFactoryBean; import org.springframework.data.neo4j.config.NullTransactionManager; import org.springframework.data.neo4j.core.GraphDatabase; import org.springframework.data.neo4j.rest.support.RestTestHelper; import org.springframework.data.neo4j.template.Neo4jTemplateApiTests; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.jta.JtaTransactionManager; +import org.springframework.transaction.jta.UserTransactionAdapter; + +import javax.transaction.TransactionManager; public class RestNeo4jTemplateApiTests extends Neo4jTemplateApiTests { @@ -64,7 +68,8 @@ public class RestNeo4jTemplateApiTests extends Neo4jTemplateApiTests @Override protected PlatformTransactionManager createTransactionManager() { - return new JtaTransactionManager(new NullTransactionManager()); + TransactionManager txm = graphDatabase.getTransactionManager(); + return new JtaTransactionManager(new UserTransactionAdapter( txm ), txm); } @Override diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestNodeEntityTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestNodeEntityTests.java index f6f901d12..987c4e3f0 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestNodeEntityTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestNodeEntityTests.java @@ -35,7 +35,7 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTests-context.xml", - "classpath:RestTests-context.xml"}) + "classpath:RestTests-context-index.xml"}) public class RestNodeEntityTests extends NodeEntityTests { @BeforeClass @@ -59,7 +59,7 @@ public class RestNodeEntityTests extends NodeEntityTests { // super.testSetShortProperty(); } - @Test(expected = CypherTransactionExecutionException.class) + @Test(expected = IllegalStateException.class) public void testDefaultFailOnDuplicateSetToTrueCausesExceptionWhenAnotherDuplicateEntityCreated() { super.testDefaultFailOnDuplicateSetToTrueCausesExceptionWhenAnotherDuplicateEntityCreated(); } diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestProjectionTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestProjectionTests.java index eaf7f57fc..b04ea9a56 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestProjectionTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestProjectionTests.java @@ -36,7 +36,7 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTests-context.xml", "classpath:RestTests-context.xml"}) -@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class}) + public class RestProjectionTests extends ProjectionTests { @BeforeClass diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestPropertyTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestPropertyTests.java index 1611ba4bb..cb7c638a9 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestPropertyTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestPropertyTests.java @@ -36,7 +36,7 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTests-context.xml", "classpath:RestTests-context.xml"}) -@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class}) + public class RestPropertyTests extends PropertyTests { @BeforeClass diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestRelationshipEntityTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestRelationshipEntityTests.java index 2584aa258..bfd7cace2 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestRelationshipEntityTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestRelationshipEntityTests.java @@ -19,6 +19,7 @@ package org.springframework.data.neo4j.rest.integration; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.runner.RunWith; import org.springframework.data.neo4j.aspects.support.RelationshipEntityTests; import org.springframework.data.neo4j.rest.support.RestTestBase; @@ -33,10 +34,10 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi * @author mh * @since 28.03.11 */ + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTests-context.xml", "classpath:RestTests-context.xml"}) -@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class}) public class RestRelationshipEntityTests extends RelationshipEntityTests { @BeforeClass diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestRelationshipTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestRelationshipTests.java index f4521838f..00073f538 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestRelationshipTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestRelationshipTests.java @@ -49,7 +49,7 @@ import static org.junit.Assert.assertEquals; */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = RestRelationshipTests.MyConfig.class) -@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class}) + public class RestRelationshipTests { @Configuration diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestUniqueEntityTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestUniqueEntityTests.java index 1dcc6a607..718808560 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestUniqueEntityTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/integration/RestUniqueEntityTests.java @@ -39,7 +39,7 @@ import static org.junit.Assert.assertEquals; @ContextConfiguration(locations = { "classpath:unique-legacy-test-context.xml", "classpath:RestTests-context.xml"}) -@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class}) + public class RestUniqueEntityTests extends UniqueLegacyIndexBasedEntityTests { @BeforeClass diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestEntityTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestEntityTests.java index 41e0b15d3..6df26d1a8 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestEntityTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestEntityTests.java @@ -22,6 +22,7 @@ import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.NotFoundException; import org.neo4j.graphdb.Relationship; +import org.neo4j.rest.graphdb.query.CypherTransactionExecutionException; import java.util.Arrays; @@ -73,7 +74,7 @@ public class RestEntityTests extends RestTestBase { assertEquals(null, restGraphDatabase.getNodeById(nodeId)); } - @Test(expected = NotFoundException.class) + @Test(expected = RuntimeException.class) public void testRemoveRelationship() { Node refNode = createNode(); Node node = createNode(); diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestQueryEngineTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestQueryEngineTests.java index 7b301177f..070ce9f70 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestQueryEngineTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestQueryEngineTests.java @@ -21,11 +21,13 @@ import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.neo4j.rest.graphdb.RestGraphDatabase; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.neo4j.aspects.support.query.QueryEngineTests; import org.springframework.data.neo4j.core.GraphDatabase; import org.springframework.data.neo4j.rest.SpringCypherRestGraphDatabase; import org.springframework.data.neo4j.rest.SpringCypherRestGraphDatabase; +import org.springframework.data.neo4j.rest.SpringRestGraphDatabase; import org.springframework.test.context.CleanContextCacheTestExecutionListener; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; @@ -40,11 +42,11 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTests-context.xml", - "classpath:RestTests-context.xml"}) + "classpath:RestTests-context-index.xml"}) public class RestQueryEngineTests extends QueryEngineTests { @Autowired - SpringCypherRestGraphDatabase restGraphDatabase; + SpringRestGraphDatabase restGraphDatabase; @BeforeClass public static void startDb() throws Exception { diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestTestBase.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestTestBase.java index 43a488fca..3e85e3c06 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestTestBase.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestTestBase.java @@ -57,6 +57,7 @@ public class RestTestBase { db = new ImpermanentGraphDatabase(); final ServerConfigurator configurator = new ServerConfigurator(db); configurator.configuration().setProperty(Configurator.WEBSERVER_PORT_PROPERTY_KEY,PORT); + configurator.configuration().setProperty("dbms.security.auth_enabled",false); final WrappingNeoServerBootstrapper bootstrapper = new WrappingNeoServerBootstrapper(db, configurator); int exit = bootstrapper.start(); if (exit != 0 ) throw new IllegalStateException("Server not started correctly."); diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestTestHelper.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestTestHelper.java index ecc6cbbe1..4fa5309bd 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestTestHelper.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/RestTestHelper.java @@ -41,6 +41,7 @@ public class RestTestHelper db = new ImpermanentGraphDatabase(); final ServerConfigurator configurator = new ServerConfigurator(db); configurator.configuration().setProperty(Configurator.WEBSERVER_PORT_PROPERTY_KEY,PORT); + configurator.configuration().setProperty("dbms.security.auth_enabled",false); final WrappingNeoServerBootstrapper bootstrapper = new WrappingNeoServerBootstrapper(db, configurator); bootstrapper.start(); neoServer = bootstrapper.getServer(); diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/SpringPluginInitializerTests.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/SpringPluginInitializerTests.java index 953df212d..311808a67 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/SpringPluginInitializerTests.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/neo4j/rest/support/SpringPluginInitializerTests.java @@ -74,6 +74,7 @@ public class SpringPluginInitializerTests extends SpringPluginInitializer implem }; final Configuration configuration = configurator.configuration(); configuration.setProperty(Configurator.WEBSERVER_PORT_PROPERTY_KEY, PORT); + configuration.setProperty("dbms.security.auth_enabled", false); final WrappingNeoServerBootstrapper bootstrapper = new WrappingNeoServerBootstrapper(db, configurator); touched=0; bootstrapper.start(); diff --git a/spring-data-neo4j-rest/src/test/resources/RestTests-context-index.xml b/spring-data-neo4j-rest/src/test/resources/RestTests-context-index.xml new file mode 100644 index 000000000..4a9acd80b --- /dev/null +++ b/spring-data-neo4j-rest/src/test/resources/RestTests-context-index.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/spring-data-neo4j-rest/src/test/resources/server-test-db.properties b/spring-data-neo4j-rest/src/test/resources/server-test-db.properties index faba9ee75..909653ff0 100644 --- a/spring-data-neo4j-rest/src/test/resources/server-test-db.properties +++ b/spring-data-neo4j-rest/src/test/resources/server-test-db.properties @@ -1,2 +1,4 @@ org.neo4j.server.database.location=target/test-db org.neo4j.server.thirdparty_jaxrs_classes=org.springframework.data.neo4j.rest.support=/test +dbms.security.auth_enabled=false + diff --git a/spring-data-neo4j-rest/src/test/resources/test-db.properties b/spring-data-neo4j-rest/src/test/resources/test-db.properties index 64291a371..f8cd64f32 100644 --- a/spring-data-neo4j-rest/src/test/resources/test-db.properties +++ b/spring-data-neo4j-rest/src/test/resources/test-db.properties @@ -1 +1,2 @@ org.neo4j.server.database.location=target/test-db +dbms.security.auth_enabled=false diff --git a/spring-data-neo4j-tx/pom.xml b/spring-data-neo4j-tx/pom.xml index a211d011f..a3880b630 100644 --- a/spring-data-neo4j-tx/pom.xml +++ b/spring-data-neo4j-tx/pom.xml @@ -53,25 +53,6 @@ - - org.neo4j - neo4j-kernel - ${neo4j.version} - - - org.neo4j - neo4j-lucene-index - ${neo4j.version} - test - - - org.neo4j - neo4j-kernel - ${neo4j.version} - test - test-jar - - org.ow2.jotm jotm-core diff --git a/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/DefaultSynchronizationManager.java b/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/DefaultSynchronizationManager.java deleted file mode 100644 index 4cca62b1d..000000000 --- a/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/DefaultSynchronizationManager.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * 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.transaction; - -import org.springframework.transaction.support.TransactionSynchronizationManager; - -/** - * @author mh - * @since 15.02.11 - */ -public class DefaultSynchronizationManager implements SynchronizationManager { - @Override - public void initSynchronization() { - TransactionSynchronizationManager.initSynchronization(); - } - - @Override - public boolean isSynchronizationActive() { - return TransactionSynchronizationManager.isSynchronizationActive(); - } - - @Override - public void clearSynchronization() { - TransactionSynchronizationManager.clear(); - } -} diff --git a/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/JotmFactoryBean.java b/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/JotmFactoryBean.java deleted file mode 100644 index 90f9ef609..000000000 --- a/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/JotmFactoryBean.java +++ /dev/null @@ -1,171 +0,0 @@ -/** - * 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.transaction; - -import org.objectweb.jotm.Current; -import org.objectweb.jotm.Jotm; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; - -import javax.naming.NamingException; -import javax.transaction.SystemException; - -/** - * FactoryBean that retrieves the JTA UserTransaction/TransactionManager for - * ObjectWeb's JOTM. Will retrieve - * an already active JOTM instance if found (e.g. if running in JOnAS), - * else create a new local JOTM instance. - *

- *

With JOTM, the same object implements both the - * {@link javax.transaction.UserTransaction} and the - * {@link javax.transaction.TransactionManager} interface, - * as returned by this FactoryBean. - *

- *

A local JOTM instance is well-suited for working in conjunction with - * ObjectWeb's XAPool, e.g. with bean - * definitions like the following: - *

- *

- * <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>
- * 

- * <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> - * <property name="userTransaction" ref="jotm"/> - * </bean> - *

- * <bean id="innerDataSource" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"> - * <property name="transactionManager" ref="jotm"/> - * <property name="driverName" value="..."/> - * <property name="url" value="..."/> - * <property name="user" value="..."/> - * <property name="password" value="..."/> - * </bean> - *

- * <bean id="dataSource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"> - * <property name="dataSource" ref="innerDataSource"/> - * <property name="user" value="..."/> - * <property name="password" value="..."/> - * <property name="maxSize" value="..."/> - * </bean>

- *

- * Note that Spring's {@link org.springframework.transaction.jta.JtaTransactionManager} will automatically detect - * that the passed-in UserTransaction reference also implements the - * TransactionManager interface. Hence, it is not necessary to specify a - * separate reference for JtaTransactionManager's "transactionManager" property. - *

- *

Implementation note: This FactoryBean uses JOTM's static access method - * to obtain the JOTM {@link org.objectweb.jotm.Current} object, which - * implements both the UserTransaction and the TransactionManager interface, - * as mentioned above. - * - * @author Juergen Hoeller - * @see org.springframework.transaction.jta.JtaTransactionManager#setUserTransaction - * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager - * @see org.objectweb.jotm.Current - * @since 21.01.2004 - */ -public class JotmFactoryBean implements FactoryBean, DisposableBean, InitializingBean { - - private Current jotmCurrent; - - private Jotm jotm; - private String jotmHome; - private Integer defaultTimeout; - private Boolean transactionRecovery; - - - /** - * Set the default transaction timeout for the JOTM instance. - *

Should only be called for a local JOTM instance, - * not when accessing an existing (shared) JOTM instance. - */ - public void setDefaultTimeout(int defaultTimeout) { - this.defaultTimeout = defaultTimeout; - } - - - public void setTransactionRecovery(boolean transactionRecovery) throws SystemException { - this.transactionRecovery = transactionRecovery; - } - - /** - * @param jotmHome the directory that contains conf/jotm.properties - */ - public void setJotmHome(String jotmHome) { - this.jotmHome = jotmHome; - } - - @Override - public void afterPropertiesSet() throws Exception { - createJotm(); - } - - private void createJotm() throws NamingException, SystemException { - if (jotmHome!=null) { - System.setProperty("jotm.home",jotmHome); - } - // Check for already active JOTM instance. - this.jotmCurrent = Current.getCurrent(); - - // If none found, create new local JOTM instance. - if (this.jotmCurrent == null) { - // Only for use within the current Spring context: - // local, not bound to registry. - this.jotm = new Jotm(true, false); - this.jotmCurrent = Current.getCurrent(); - } - if (defaultTimeout!=null) { - this.jotmCurrent.setDefaultTimeout(defaultTimeout); - } - if (transactionRecovery!=null) { - this.jotmCurrent.setTransactionRecovery(transactionRecovery); - } - } - - /** - * Return the JOTM instance created by this factory bean, if any. - * Will be null if an already active JOTM instance is used. - *

Application code should never need to access this. - */ - public Jotm getJotm() { - return this.jotm; - } - - - public Object getObject() { - return this.jotmCurrent; - } - - public Class getObjectType() { - return this.jotmCurrent.getClass(); - } - - public boolean isSingleton() { - return true; - } - - - /** - * Stop the local JOTM instance, if created by this FactoryBean. - */ - public void destroy() { - if (this.jotm != null) { - this.jotm.stop(); - } - } - -} diff --git a/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/MultiTransactionStatus.java b/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/MultiTransactionStatus.java deleted file mode 100644 index abb83b0fc..000000000 --- a/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/MultiTransactionStatus.java +++ /dev/null @@ -1,167 +0,0 @@ -/** - * 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.transaction; - -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionException; -import org.springframework.transaction.TransactionStatus; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -/** - * @author mh - * @since 14.02.11 - */ -public class MultiTransactionStatus implements TransactionStatus { - - - private PlatformTransactionManager mainTransactionManager; - - private Map transactionStatuses = - Collections.synchronizedMap(new HashMap()); - - private boolean newSynchonization; - - public MultiTransactionStatus(PlatformTransactionManager mainTransactionManager) { - this.mainTransactionManager = mainTransactionManager; - } - - - protected Map getTransactionStatuses() { - return transactionStatuses; - } - - private TransactionStatus getMainTransactionStatus() { - return transactionStatuses.get(mainTransactionManager); - } - - - public void setNewSynchonization() { - this.newSynchonization = true; - } - - public boolean isNewSynchonization() { - return newSynchonization; - } - - - @Override - public boolean isNewTransaction() { - return getMainTransactionStatus().isNewTransaction(); - } - - @Override - public boolean hasSavepoint() { - return getMainTransactionStatus().hasSavepoint(); - } - - @Override - public void setRollbackOnly() { - for(TransactionStatus ts : transactionStatuses.values() ){ - ts.setRollbackOnly(); - } - } - - @Override - public boolean isRollbackOnly() { - return getMainTransactionStatus().isRollbackOnly(); - } - - @Override - public boolean isCompleted() { - return getMainTransactionStatus().isCompleted(); - } - - - private static class SavePoints { - Map savepoints=new HashMap(); - - private void addSavePoint(TransactionStatus status, Object savepoint) { - this.savepoints.put(status, savepoint); - } - - private void save(TransactionStatus transactionStatus) { - Object savepoint = transactionStatus.createSavepoint(); - addSavePoint(transactionStatus, savepoint); - } - - - public void rollback() { - for (TransactionStatus transactionStatus : savepoints.keySet()) { - transactionStatus.rollbackToSavepoint(savepointFor(transactionStatus)); - } - } - - private Object savepointFor(TransactionStatus transactionStatus) { - return savepoints.get(transactionStatus); - } - - public void release() { - for (TransactionStatus transactionStatus : savepoints.keySet()) { - transactionStatus.releaseSavepoint(savepointFor(transactionStatus)); - } - } - } - - @Override - public Object createSavepoint() throws TransactionException { - SavePoints savePoints = new SavePoints(); - - for (TransactionStatus transactionStatus : transactionStatuses.values()) { - savePoints.save(transactionStatus); - } - return savePoints; - } - - @Override - public void rollbackToSavepoint(Object savepoint) throws TransactionException { - SavePoints savePoints= (SavePoints) savepoint; - savePoints.rollback(); - } - - @Override - public void releaseSavepoint(Object savepoint) throws TransactionException { - ((SavePoints)savepoint).release(); - } - - public void registerTransactionManager(TransactionDefinition definition, PlatformTransactionManager transactionManager) { - getTransactionStatuses().put(transactionManager, transactionManager.getTransaction(definition)); - } - - void commit(PlatformTransactionManager transactionManager) { - TransactionStatus transactionStatus = getTransactionStatus(transactionManager); - transactionManager.commit(transactionStatus); - } - - private TransactionStatus getTransactionStatus(PlatformTransactionManager transactionManager) { - return this.getTransactionStatuses().get(transactionManager); - } - - void rollback(PlatformTransactionManager transactionManager) { - transactionManager.rollback(getTransactionStatus(transactionManager)); - } - - @Override - public void flush() { - for (TransactionStatus transactionStatus : transactionStatuses.values()) { - transactionStatus.flush(); - } - } -} \ No newline at end of file diff --git a/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/SpringProvider.java b/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/SpringProvider.java deleted file mode 100644 index 6f3462831..000000000 --- a/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/SpringProvider.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * 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.transaction; - -import org.neo4j.helpers.Service; -import org.neo4j.kernel.impl.core.KernelPanicEventGenerator; -import org.neo4j.kernel.impl.nioneo.store.FileSystemAbstraction; -import org.neo4j.kernel.impl.transaction.*; -import org.neo4j.kernel.impl.util.StringLogger; -import org.springframework.beans.factory.annotation.Configurable; - -@Configurable -@Service.Implementation( TransactionManagerProvider.class ) -public class SpringProvider extends TransactionManagerProvider -{ - public SpringProvider() - { - super( "spring-jta" ); - } - - @Override - public AbstractTransactionManager loadTransactionManager( String txLogDir, - XaDataSourceManager xaDataSourceManager, - KernelPanicEventGenerator kpe, - RemoteTxHook rollbackHook, - StringLogger msgLog, - FileSystemAbstraction fileSystem, - TransactionStateFactory stateFactory ) { - return new SpringServiceImpl(stateFactory,xaDataSourceManager); - } -} diff --git a/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/SpringServiceImpl.java b/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/SpringServiceImpl.java deleted file mode 100644 index 3288a39cd..000000000 --- a/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/SpringServiceImpl.java +++ /dev/null @@ -1,215 +0,0 @@ -/** - * 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.transaction; - -import org.neo4j.kernel.api.KernelAPI; -import org.neo4j.kernel.api.KernelTransaction; -import org.neo4j.kernel.impl.core.TransactionState; -import org.neo4j.kernel.impl.transaction.AbstractTransactionManager; -import org.neo4j.kernel.impl.transaction.TransactionStateFactory; -import org.neo4j.kernel.impl.transaction.XaDataSourceManager; -import org.neo4j.kernel.impl.transaction.xaframework.XaDataSource; -import org.objectweb.jotm.Current; -import org.objectweb.jotm.TransactionResourceManager; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Configurable; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.jta.JtaTransactionManager; - -import javax.transaction.*; -import javax.transaction.xa.XAException; -import javax.transaction.xa.XAResource; -import java.util.HashMap; -import java.util.Map; -import java.util.WeakHashMap; - -/** - * @author Chris Gioran - */ -@Configurable -class SpringServiceImpl extends AbstractTransactionManager -{ - private PlatformTransactionManager transactionManager; - - private TransactionManager delegate; - - private final Map states = new WeakHashMap(); -// private final Map kernelTransactions = new WeakHashMap(); - private final TransactionStateFactory stateFactory; - private XaDataSourceManager xaDataSourceManager; - private KernelAPI kernelAPI; - - SpringServiceImpl(TransactionStateFactory stateFactory, XaDataSourceManager xaDataSourceManager) - { - this.stateFactory = stateFactory; - this.xaDataSourceManager = xaDataSourceManager; - } - - @Override - public void init() throws Throwable { - if (transactionManager instanceof JtaTransactionManager) { - delegate = ((JtaTransactionManager) transactionManager).getTransactionManager(); - } else { - throw new IllegalStateException("Injected transaction manager is not of type JtaTransactionManager but "+ transactionManager.getClass().getName()); - } - } - - @Override - public void doRecovery() throws Throwable - { - TransactionResourceManager trm = new TransactionResourceManager() - { - @Override - public void returnXAResource( String rmName, XAResource rmXares ) - { - } - }; - - try - { - for ( XaDataSource xaDs : xaDataSourceManager.getAllRegisteredDataSources() ) - { - Current.getTransactionRecovery().registerResourceManager( xaDs.getName(), - xaDs.getXaConnection().getXaResource(), xaDs.getName(), trm ); - } - Current.getTransactionRecovery().startResourceManagerRecovery(); - } - catch ( XAException e ) - { - throw new Error( "Error registering xa datasource", e ); - } - } - - @Override - public TransactionState getTransactionState() { - try - { - TransactionState state = states.get( getTransaction() ); - return state != null ? state : TransactionState.NO_STATE; - } - catch ( SystemException e ) - { - throw new RuntimeException( e ); - } - } - - @Override - public int getEventIdentifier() { - return 0; - } - - @Override - public void start() throws Throwable { - - } - - @Override - public void shutdown() throws Throwable { - states.clear(); - } - - public void begin() throws NotSupportedException, SystemException - { - delegate.begin(); - Transaction tx = getTransaction(); - states.put(tx, stateFactory.create(tx)); -// kernelTransactions.put( tx, kernelAPI.newTransaction() ); - } - - public void commit() throws RollbackException, HeuristicMixedException, - HeuristicRollbackException, SecurityException, - IllegalStateException, SystemException - { - Transaction tx = getTransaction(); - delegate.commit(); - states.remove(tx); - } - - public int getStatus() throws SystemException - { - return delegate.getStatus(); - } - - public Transaction getTransaction() throws SystemException - { - return delegate.getTransaction(); - } - - public void resume( Transaction tobj ) throws InvalidTransactionException, - IllegalStateException, SystemException - { - delegate.resume( tobj ); - } - - public void rollback() throws IllegalStateException, SecurityException, - SystemException - { - Transaction tx = getTransaction(); - delegate.rollback(); - states.remove(tx); - } - - public void setRollbackOnly() throws IllegalStateException, SystemException - { - delegate.setRollbackOnly(); - } - - public void setTransactionTimeout( int seconds ) throws SystemException - { - delegate.setTransactionTimeout( seconds ); - } - - public Transaction suspend() throws SystemException - { - return delegate.suspend(); - } - - @Override - public void stop() - { - // Currently a no-op - } - - public PlatformTransactionManager getTransactionManager() { - return transactionManager; - } - - @Autowired - public void setTransactionManager(PlatformTransactionManager transactionManager) { - this.transactionManager = transactionManager; - } - -// @Override -// public void setKernel(KernelAPI kernelAPI) { -// this.kernelAPI = kernelAPI; -// } -// -// @Override -// public KernelTransaction getKernelTransaction() -// { -// Transaction transaction; -// try -// { -// transaction = getTransaction(); -// } -// catch ( SystemException e ) -// { -// return null; -// } -// return kernelTransactions.get( transaction ); -// } -} diff --git a/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/SynchronizationManager.java b/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/SynchronizationManager.java deleted file mode 100644 index b4159ed9f..000000000 --- a/spring-data-neo4j-tx/src/main/java/org/springframework/data/neo4j/transaction/SynchronizationManager.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * 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.transaction; - -/** - * @author mh - * @since 15.02.11 - */ -public interface SynchronizationManager { - void initSynchronization(); - - boolean isSynchronizationActive(); - - void clearSynchronization(); -} diff --git a/spring-data-neo4j-tx/src/test/java/org/springframework/data/neo4j/transaction/JOTMIntegrationTests.java b/spring-data-neo4j-tx/src/test/java/org/springframework/data/neo4j/transaction/JOTMIntegrationTests.java deleted file mode 100644 index 244f54ff4..000000000 --- a/spring-data-neo4j-tx/src/test/java/org/springframework/data/neo4j/transaction/JOTMIntegrationTests.java +++ /dev/null @@ -1,145 +0,0 @@ -/** - * 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.transaction; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.NotFoundException; -import org.neo4j.graphdb.factory.GraphDatabaseSettings; -import org.neo4j.kernel.AbstractGraphDatabase; -import org.neo4j.kernel.GraphDatabaseAPI; -import org.neo4j.kernel.KernelData; -import org.neo4j.kernel.configuration.Config; -import org.objectweb.jotm.Current; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.transaction.jta.JtaTransactionManager; -import org.springframework.transaction.jta.ManagedTransactionAdapter; - -import javax.transaction.NotSupportedException; -import javax.transaction.SystemException; -import javax.transaction.Transaction; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * @author mh - * @since 21.02.11 - */ - -public class JOTMIntegrationTests { - private ClassPathXmlApplicationContext ctx; - private GraphDatabaseService gds; - - @Before - public void setUp() throws Exception { - ctx = new ClassPathXmlApplicationContext("classpath:spring-tx-text-context.xml"); - gds = ctx.getBean(GraphDatabaseService.class); - } - - @After - public void tearDown() throws Exception { - if (ctx != null) ctx.close(); - } - - @Test - public void createdNodeShouldBeFoundAfterCommit() throws Exception { - org.neo4j.graphdb.Transaction transaction = gds.beginTx(); - Node node = null; - try { - node = gds.createNode(); - assertNotNull(node); - transaction.success(); - } finally { - transaction.finish(); - } - - transaction = gds.beginTx(); - try { - Node readBackOutsideOfTx = gds.getNodeById(node.getId()); - Assert.assertEquals(node, readBackOutsideOfTx); - } finally { - transaction.success(); - transaction.finish(); - } - try { - transaction = gds.beginTx(); - Node readBackInsideOfTx = gds.getNodeById(node.getId()); - Assert.assertEquals(node, readBackInsideOfTx); - transaction.success(); - } finally { - transaction.finish(); - } - } - - @Test - public void indexedNodeShouldBeFound() throws Exception { - org.neo4j.graphdb.Transaction transaction = gds.beginTx(); - Node node = null; - try { - node = gds.createNode(); - gds.index().forNodes("node").add(node, "name", "value"); - transaction.success(); - } finally { - transaction.finish(); - } - transaction = gds.beginTx(); - try { - Node retrievedNode = gds.index().forNodes("node").get("name", "value").getSingle(); - Assert.assertEquals(node, retrievedNode); - } finally { - transaction.success(); - transaction.finish(); - } - } - - @Test(expected = NotFoundException.class) - public void createdNodeShouldBeNotAvailableAfterRollback() throws Exception { - org.neo4j.graphdb.Transaction tx = gds.beginTx(); - long nodeId=0; - try { - Node node = gds.createNode(); - nodeId = node.getId(); - tx.failure(); - } finally { - tx.close(); - } - tx = gds.beginTx(); - try { - gds.getNodeById(nodeId); - } finally { - tx.success(); - tx.close(); - } - } - - @Test - public void databaseConfiguredWithSpringJtaShouldUseJtaTransactionManager() throws SystemException, NotSupportedException { - final Config config = ((GraphDatabaseAPI) gds).getDependencyResolver().resolveDependency(Config.class); - Assert.assertEquals("spring-jta", config.getParams().get(GraphDatabaseSettings.tx_manager_impl.name())); - - JtaTransactionManager tm = ctx.getBean("transactionManager", JtaTransactionManager.class); - Transaction transaction = tm.createTransaction("jotm", 1000); - - Assert.assertEquals(ManagedTransactionAdapter.class, transaction.getClass()); - assertEquals(Current.class, ((ManagedTransactionAdapter) transaction).getTransactionManager().getClass()); - } -} diff --git a/spring-data-neo4j/src/main/java/org/neo4j/graphdb/ExecutionPlanDescription.java b/spring-data-neo4j/src/main/java/org/neo4j/graphdb/ExecutionPlanDescription.java new file mode 100644 index 000000000..afcf774b5 --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/neo4j/graphdb/ExecutionPlanDescription.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2002-2015 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.graphdb; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Instances describe single execution steps in a Cypher query execution plan + * + * Execution plans form a tree of execution steps. Each step is described by a {@link ExecutionPlanDescription} object. + */ +public interface ExecutionPlanDescription +{ + /** + * Retrieves the name of this execution step. + * + * @return descriptive name for this kind of execution step + */ + String getName(); + + /** + * Retrieves the children of this execution step. + * + * @return list of previous (child) execution step descriptions + */ + List getChildren(); + + /** + * Retrieve argument map for the associated execution step + * + * Valid arguments are all Java primitive values, Strings, Arrays of those, and Maps from Strings to + * valid arguments. Results are guaranteed to be trees (i.e. there are no cyclic dependencies among values) + * + * @return a map containing arguments that describe this execution step in more detail + */ + Map getArguments(); + + /** + * @return the set of identifiers used in this execution step + */ + public Set getIdentifiers(); + + /** + * Signifies that the query was profiled, and that statistics from the profiling can + * {@link #getProfilerStatistics() be retrieved}. + * + * The {@code PROFILE} directive in Cypher + * ensures the presence of profiler statistics in the plan description. + * + * @return true, if {@link ProfilerStatistics} are available for this execution step + */ + boolean hasProfilerStatistics(); + + /** + * Retrieve the statistics collected from profiling this query. + * + * If the query was not profiled, this method will throw {@link java.util.NoSuchElementException}. + * + * @return profiler statistics for this execution step iff available + * @throws java.util.NoSuchElementException iff profiler statistics are not available + */ + ProfilerStatistics getProfilerStatistics(); + + /** + * Instances describe statistics from the profiler of a particular step in the execution plan. + */ + interface ProfilerStatistics + { + /** + * @return number of rows processed by the associated execution step + */ + long getRows(); + + /** + * @return number of database hits (potential disk accesses) caused by executing the associated execution step + */ + long getDbHits(); + } +} diff --git a/spring-data-neo4j/src/main/java/org/neo4j/graphdb/QueryExecutionType.java b/spring-data-neo4j/src/main/java/org/neo4j/graphdb/QueryExecutionType.java new file mode 100644 index 000000000..d036ab485 --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/neo4j/graphdb/QueryExecutionType.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2002-2015 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.graphdb; + +import static java.util.Objects.requireNonNull; + +/** + * Signifies how a query is executed, as well as what side effects and results could be expected from the query. + *

+ * In Cypher there are three different modes of execution: + *

+ * Instances of this class contain the required information to be able to tell these different execution modes apart. + * It also contains information about what effects the query could have, and whether it could yield any results, in + * form + * of the {@link QueryType QueryType enum}. + *

+ * Queries executed with the {@code PROFILE} directive can have side effects and produce results in the same way as a + * normally executed method. The difference being that the user has expressed an interest in seeing the plan used to + * execute the query, and that this plan will (after execution completes) be annotated with + * {@linkplain org.neo4j.graphdb.ExecutionPlanDescription#getProfilerStatistics() profiling information} from the execution of the query. + *

+ * Queries executed with the {@code EXPLAIN} directive never have any side effects, nor do they ever yield any rows in + * the results, the sole purpose of this mode of execution is to + * {@linkplain org.neo4j.graphdb.Result#getExecutionPlanDescription() get a description of the plan} that would be executed + * if/when the query is executed normally (or under {@code PROFILE}). + */ +public final class QueryExecutionType +{ + /** + * Signifies what type of query an {@link QueryExecutionType} executes. + */ + public enum QueryType + { + /** A read-only query, that does not change any data, but only produces a result. */ + READ_ONLY, + /** A read/write query, that creates or updates data, and also produces a result. */ + READ_WRITE, + /** A write-only query, that creates or updates data, but does not yield any rows in the result. */ + WRITE, + /** + * A schema changing query, that updates the schema but neither changes any data nor yields any rows in the + * result. + */ + SCHEMA_WRITE,; + private final QueryExecutionType query, profiled, explained; + + QueryType() + { + this.query = new QueryExecutionType( Execution.QUERY, this ); + this.profiled = new QueryExecutionType( Execution.PROFILE, this ); + this.explained = new QueryExecutionType( Execution.EXPLAIN, this ); + } + } + + /** + * Get the {@link QueryExecutionType} that signifies normal execution of a query of the supplied type. + * + * @param type the type of query executed. + * @return The instance that signifies normal execution of the supplied {@link QueryType}. + */ + public static QueryExecutionType query( QueryType type ) + { + return requireNonNull( type, "QueryType" ).query; + } + + /** + * Get the {@link QueryExecutionType} that signifies profiled execution of a query of the supplied type. + * + * @param type the type of query executed. + * @return The instance that signifies profiled execution of the supplied {@link QueryType}. + */ + public static QueryExecutionType profiled( QueryType type ) + { + return requireNonNull( type, "QueryType" ).profiled; + } + + /** + * Get the {@link QueryExecutionType} that signifies explaining the plan of a query of the supplied type. + * + * @param type the type of query executed. + * @return The instance that signifies explaining the plan of the supplied {@link QueryType}. + */ + public static QueryExecutionType explained( QueryType type ) + { + return requireNonNull( type, "QueryType" ).explained; + } + + /** + * Get the type of query this execution refers to. + * + * @return the type of query this execution refers to. + */ + public QueryType queryType() + { + return type; + } + + /** + * Signifies whether results from this execution + * {@linkplain org.neo4j.graphdb.ExecutionPlanDescription#getProfilerStatistics() contains profiling information}. + * + * This is {@code true} for queries executed with the + * {@code PROFILE} directive. + * + * @return {@code true} if the results from this execution would contain profiling information. + */ + public boolean isProfiled() + { + return execution == Execution.PROFILE; + } + + /** + * Signifies whether the supplied query contained a directive that asked for a + * {@linkplain org.neo4j.graphdb.ExecutionPlanDescription description of the execution plan}. + * + * This is {@code true} for queries executed with either the + * {@code EXPLAIN} or {@code PROFILE} directives. + * + * @return {@code true} if a description of the plan should be presented to the user. + */ + public boolean requestedExecutionPlanDescription() + { + return execution != Execution.QUERY; + } + + /** + * Signifies that the query was executed with the + * {@code EXPLAIN} directive. + * + * @return {@code true} if the query was executed using the {@code EXPLAIN} directive. + */ + public boolean isExplained() + { + return execution == Execution.EXPLAIN; + } + + /** + * Signifies that the execution of the query could produce a result. + * + * This is an important distinction from the result being empty. + * + * @return {@code true} if the execution would yield rows in the result set. + */ + public boolean canContainResults() + { + return (type == QueryType.READ_ONLY || type == QueryType.READ_WRITE) && execution != Execution.EXPLAIN; + } + + /** + * Signifies that the execution of the query could perform changes to the data. + * + * {@link org.neo4j.graphdb.Result}{@link org.neo4j.graphdb.Result#getQueryStatistics() .getQueryStatistics()}{@link org.neo4j.graphdb.QueryStatistics#containsUpdates() + * .containsUpdates()} signifies whether the query actually performed any updates. + * + * @return {@code true} if the execution could perform changes to data. + */ + public boolean canUpdateData() + { + return (type == QueryType.READ_WRITE || type == QueryType.WRITE) && execution != Execution.EXPLAIN; + } + + /** + * Signifies that the execution of the query updates the schema. + * + * @return {@code true} if the execution updates the schema. + */ + public boolean canUpdateSchema() + { + return type == QueryType.SCHEMA_WRITE && execution != Execution.EXPLAIN; + } + + private final Execution execution; + private final QueryType type; + + private QueryExecutionType(Execution execution, QueryType type) + { + this.execution = execution; + this.type = type; + } + + @Override + public String toString() + { + return execution.toString( type ); + } + + private enum Execution + { + QUERY + { + @Override + String toString( QueryType type ) + { + return type.name(); + } + }, + PROFILE, + EXPLAIN,; + + String toString( QueryType type ) + { + return name() + ":" + type.name(); + } + } +} diff --git a/spring-data-neo4j/src/main/java/org/neo4j/graphdb/QueryStatistics.java b/spring-data-neo4j/src/main/java/org/neo4j/graphdb/QueryStatistics.java new file mode 100644 index 000000000..81564a233 --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/neo4j/graphdb/QueryStatistics.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2002-2015 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.graphdb; + +/** + * Represents statistics about the effects of a query. + * + * If the query did not perform any {@link #containsUpdates() updates}, all the methods of this interface will return + * {@code 0}. + */ +public interface QueryStatistics +{ + /** + * Returns the number of nodes created by this query. + * + * @return the number of nodes created by this query. + */ + int getNodesCreated(); + + /** + * Returns the number of nodes deleted by this query. + * + * @return the number of nodes deleted by this query. + */ + int getNodesDeleted(); + + /** + * Returns the number of relationships created by this query. + * + * @return the number of relationships created by this query. + */ + int getRelationshipsCreated(); + + /** + * Returns the number of relationships deleted by this query. + * + * @return the number of relationships deleted by this query. + */ + int getRelationshipsDeleted(); + + /** + * Returns the number of properties set by this query. Setting a property to the same value again still counts + * towards this. + * + * @return the number of properties set by this query. + */ + int getPropertiesSet(); + + /** + * Returns the number of labels added to any node by this query. + * + * @return the number of labels added to any node by this query. + */ + int getLabelsAdded(); + + /** + * Returns the number of labels removed from any node by this query. + * + * @return the number of labels removed from any node by this query. + */ + int getLabelsRemoved(); + + /** + * Returns the number of indexes added by this query. + * + * @return the number of indexes added by this query. + */ + int getIndexesAdded(); + + /** + * Returns the number of indexes removed by this query. + * + * @return the number of indexes removed by this query. + */ + int getIndexesRemoved(); + + /** + * Returns the number of constraints added by this query. + * + * @return the number of constraints added by this query. + */ + int getConstraintsAdded(); + + /** + * Returns the number of constraints removed by this query. + * + * @return the number of constraints removed by this query. + */ + int getConstraintsRemoved(); + + /** + * If the query updated the graph in any way, this method will return true. + * + * @return if the graph has been updated. + */ + boolean containsUpdates(); +} diff --git a/spring-data-neo4j/src/main/java/org/neo4j/graphdb/Result.java b/spring-data-neo4j/src/main/java/org/neo4j/graphdb/Result.java new file mode 100644 index 000000000..c72cddbeb --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/neo4j/graphdb/Result.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2002-2015 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.graphdb; + +import java.io.PrintWriter; +import java.util.List; +import java.util.Map; + +/** + * Represents the result of {@link org.neo4j.graphdb.GraphDatabaseService#execute(String, java.util.Map) executing} a query. + *

+ * The result is comprised of a number of rows, potentially computed lazily, with this result object being an iterator + * over those rows. Each row is represented as a {@link java.util.Map}<{@link String}, {@link Object}>, the + * keys in this map are the names of the columns in the row, as specified by the {@code return} clause of the query, + * and the values of the map is the corresponding computed value of the expression in the {@code return} clause. Each + * row will thus have the same set of keys, and these keys can be retrieved using the + * {@linkplain #columns() columns-method}. + *

+ * To ensure that any resource, including transactions bound to the query, are properly freed, the result must either + * be fully exhausted, by means of the {@linkplain java.util.Iterator iterator protocol}, or the result has to be + * explicitly closed, by invoking the {@linkplain #close() close-method}. + *

+ * Idiomatic use of the Result object would look like this: + *


+ * try ( Result result = graphDatabase.execute( query, parameters ) )
+ * {
+ *     while ( result.hasNext() )
+ *     {
+ *         Map<String, Object> row = result.next();
+ *         for ( String key : result.columns() )
+ *         {
+ *             System.out.printf( "%s = %s%n", key, row.get( key ) );
+ *         }
+ *     }
+ * }
+ * 
+ * If the result consists of only a single column, or if only one of the columns is of interest, a projection can be + * extracted using {@link #columnAs(String)}. This produces a new iterator over the values of the named column. It + * should be noted that this iterator consumes the rows of the result in the same way as invoking {@link #next()} on + * this object would, and that the {@link #close() close-method} on either iterator has the same effect. It is thus + * safe to either close the projected column iterator, or this iterator, or both if all rows have not been consumed. + *

+ * In addition to the {@link #next() iteration methods} on this interface, {@link #close()}, and the + * {@link #columnAs(String) column projection method}, there are two methods for getting a string representation of the + * result that also consumes the entire result if invoked. {@link #resultAsString()} returns a single string + * representation of all (remaining) rows in the result, and {@link #writeAsStringTo(java.io.PrintWriter)} does the same, but + * streams the result to the provided {@link java.io.PrintWriter} instead, without allocating large string objects. + *

+ * The methods that do not consume any rows from the result, or in other ways alter the state of the result are safe to + * invoke at any time, even after the result has been {@linkplain #close() closed} or fully exhausted. These methods + * are: + *

+ *

+ * Not all queries produce an actual result, and some queries that do might yield an empty result set. In order to + * distinguish between these cases the {@link org.neo4j.graphdb.QueryExecutionType} {@linkplain #getQueryExecutionType() of this result} + * can be queried. + */ +public interface Result extends ResourceIterator> +{ + /** + * Indicates what kind of query execution produced this result. + * + * @return an object that indicates what kind of query was executed to produce this result. + */ + QueryExecutionType getQueryExecutionType(); + + /** + * The exact names used to represent each column in the result set. + * + * @return List of the column names. + */ + List columns(); + + /** + * Returns an iterator with the result objects from a single column of the result set. This method is best used for + * single column results. + * + *

To ensure that any resources, including transactions bound to it, are properly closed, the iterator must + * either be fully exhausted, or the {@link ResourceIterator#close() close()} method must be + * called.

+ * + * @param name exact name of the column, as it appeared in the original query + * @param desired type cast for the result objects + * @return an iterator of the result objects, possibly empty + * @throws ClassCastException when the result object can not be cast to the requested type + * @throws NotFoundException when the column name does not appear in the original query + */ + ResourceIterator columnAs(String name); + + /** + * Denotes there being more rows available in this result. These rows must either be consumed, by invoking + * {@link #next()}, or the result has to be {@link #close() closed}. + * + * @return {@code true} if there is more rows available in this result, {@code false} otherwise. + */ + boolean hasNext(); + + /** + * Returns the next row in this result. + * + * @return the next row in this result. + */ + Map next(); + + /** + * Closes the result, freeing up any resources held by the result. + * + * This is an idempotent operation, invoking it multiple times has the same effect as invoking it exactly once. + * It is thus safe (and even encouraged, for style and simplicity) to invoke this method even after consuming all + * rows in the result through the {@link #next() next-method}. + */ + void close(); + + /** + * Statistics about the effects of the query. + * + * @return statistics about the effects of the query. + */ + QueryStatistics getQueryStatistics(); + + /** + * Returns a description of the query plan used to produce this result. + * + * Retrieving a description of the execution plan that was executed is always possible, regardless of whether the + * query requested a plan or not. For implementing a client with the ability to present the plan to the user, it is + * useful to be able to tell if the query requested a description of the plan or not. For these purposes the + * {@link org.neo4j.graphdb.QueryExecutionType#requestedExecutionPlanDescription()}-method is used. + * + * Being able to invoke this method, regardless of whether the user requested the plan or not is useful for + * purposes of debugging queries in applications. + * + * @return a description of the query plan used to produce this result. + */ + ExecutionPlanDescription getExecutionPlanDescription(); + + /** + * Provides a textual representation of the query result. + *

+ * The execution result represented by this object will be consumed in its entirety after this method is called. + * Calling any of the other iterating methods on it should not be expected to return any results. + *

+ * + * @return the execution result formatted as a string + */ + String resultAsString(); + + /** + * Provides a textual representation of the query result to the provided {@link java.io.PrintWriter}. + *

+ * The execution result represented by this object will be consumed in its entirety after this method is called. + * Calling any of the other iterating methods on it should not be expected to return any results. + *

+ * @param writer the {@link java.io.PrintWriter} to receive the textual representation of the query result. + */ + void writeAsStringTo(PrintWriter writer); + + /** Removing rows from the result is not supported. */ + void remove(); +} diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/EnableNeo4jRepositories.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/EnableNeo4jRepositories.java index 067c7914a..f169a34d3 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/EnableNeo4jRepositories.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/EnableNeo4jRepositories.java @@ -33,7 +33,7 @@ import org.springframework.data.repository.query.QueryLookupStrategy.Key; /** * Annotation to enable Neo4j repositories. - * + * * @author Oliver Gierke * @author Thomas Darimont */ @@ -99,10 +99,10 @@ public @interface EnableNeo4jRepositories { * {@link GraphRepositoryFactoryBean}. */ Class repositoryFactoryBeanClass() default GraphRepositoryFactoryBean.class; - + /** * Configure the repository base class to be used to create repository proxies for this particular configuration. - * + * * @return * @since 3.4 */ diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/JtaTransactionManagerFactoryBean.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/JtaTransactionManagerFactoryBean.java index b00faa108..bfc4f9bb9 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/JtaTransactionManagerFactoryBean.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/JtaTransactionManagerFactoryBean.java @@ -22,9 +22,11 @@ import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.kernel.GraphDatabaseAPI; import org.springframework.beans.factory.FactoryBean; import org.springframework.data.neo4j.core.GraphDatabase; +import org.springframework.data.neo4j.support.Neo4jEmbeddedTransactionManager; import org.springframework.transaction.jta.JtaTransactionManager; import org.springframework.transaction.jta.UserTransactionAdapter; +import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class JtaTransactionManagerFactoryBean implements FactoryBean @@ -36,6 +38,15 @@ public class JtaTransactionManagerFactoryBean implements FactoryBeanclassFor("org.neo4j.kernel.impl.transaction.SpringTransactionManager"), GraphDatabaseService.class, gds ); - } - - private UserTransaction createUserTransactionForOnePointSeven( GraphDatabaseService gds ) - { - TransactionManager txManager = ((GraphDatabaseAPI) gds).getDependencyResolver().resolveDependency(TransactionManager.class); - return createDynamically(this.classFor("org.neo4j.kernel.impl.transaction.UserTransactionImpl"), TransactionManager.class, txManager); - } - private TransactionManager createTransactionManagerForOnePointEight( GraphDatabaseService gds ) { return createDynamically( this.classFor("org.neo4j.kernel.impl.transaction.SpringTransactionManager"), GraphDatabaseAPI.class, gds ); @@ -133,6 +124,16 @@ public class JtaTransactionManagerFactoryBean implements FactoryBean T createDynamically( Class requiredClass, Class argumentClass, Object gds ) { try { diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/IndexingPropertyFieldAccessorListenerFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/IndexingPropertyFieldAccessorListenerFactory.java index bb4ddc6fa..97bb26657 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/IndexingPropertyFieldAccessorListenerFactory.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/IndexingPropertyFieldAccessorListenerFactory.java @@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty; import org.springframework.data.neo4j.support.Neo4jTemplate; +import org.springframework.data.neo4j.support.index.IndexType; public class IndexingPropertyFieldAccessorListenerFactory implements FieldAccessorListenerFactory { @@ -77,6 +78,7 @@ public class IndexingPropertyFieldAccessorListenerFactory index = template.getIndex(property, entity.getClass()); if (newVal instanceof Number && property.getIndexInfo().isNumeric()) newVal = ValueContext.numeric((Number) newVal); +// if (property.getIndexInfo().getIndexType().equals(IndexType.POINT)) return; final T state = template.getPersistentState(entity); index.remove(state, indexKey); if (newVal != null) { diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/GraphRepositoryFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/GraphRepositoryFactory.java index f93ef4cc8..09b735287 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/GraphRepositoryFactory.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/GraphRepositoryFactory.java @@ -44,7 +44,7 @@ public class GraphRepositoryFactory extends RepositoryFactorySupport { /** * Creates a new {@link GraphRepositoryFactory} from the given {@link org.springframework.data.neo4j.support.Neo4jTemplate} and * {@link MappingContext}. - * + * * @param template must not be {@literal null}. * @param mappingContext must not be {@literal null}. */ @@ -61,14 +61,14 @@ public class GraphRepositoryFactory extends RepositoryFactorySupport { /* * (non-Javadoc) * @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getTargetRepository(org.springframework.data.repository.core.RepositoryInformation) - */ + */ @Override protected Object getTargetRepository(RepositoryInformation information) { - return getTargetRepository(information, template); + return getTargetRepository(information, template); } protected Object getTargetRepository(RepositoryInformation metadata, Neo4jTemplate template) { - return getTargetRepositoryViaReflection(metadata, metadata.getDomainType(), template); + return getTargetRepositoryViaReflection(metadata, metadata.getDomainType(), template); } @Override @@ -106,4 +106,4 @@ public class GraphRepositoryFactory extends RepositoryFactorySupport { } -} \ No newline at end of file +} diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/DelegatingGraphDatabase.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/DelegatingGraphDatabase.java index 7604d0013..8163e981b 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/DelegatingGraphDatabase.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/DelegatingGraphDatabase.java @@ -25,6 +25,7 @@ import org.neo4j.graphdb.traversal.TraversalDescription; import org.neo4j.index.lucene.ValueContext; import org.neo4j.kernel.GraphDatabaseAPI; import org.neo4j.kernel.Traversal; +import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; import org.neo4j.tooling.GlobalGraphOperations; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -232,13 +233,8 @@ public class DelegatingGraphDatabase implements GraphDatabase { if (!(delegate instanceof GraphDatabaseAPI)) { return true; // assume always running tx (e.g. for REST or other remotes) } - try { - final TransactionManager txManager = ((GraphDatabaseAPI) delegate).getDependencyResolver().resolveDependency(TransactionManager.class); - return txManager.getStatus() != Status.STATUS_NO_TRANSACTION; - } catch (SystemException e) { - log.error("Error accessing TransactionManager", e); - return false; - } + final ThreadToStatementContextBridge txManager = ((GraphDatabaseAPI) delegate).getDependencyResolver().resolveDependency(ThreadToStatementContextBridge.class); + return txManager.hasTransaction(); } @Override diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/GraphDatabaseFactoryBean.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/GraphDatabaseFactoryBean.java index 592a26e89..2c8c55840 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/GraphDatabaseFactoryBean.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/GraphDatabaseFactoryBean.java @@ -17,7 +17,6 @@ package org.springframework.data.neo4j.support; import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.kernel.EmbeddedGraphDatabase; import org.springframework.beans.factory.FactoryBean; import org.springframework.data.neo4j.core.GraphDatabase; diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jExceptionTranslator.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jExceptionTranslator.java index cba61d164..1ed77b3dc 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jExceptionTranslator.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jExceptionTranslator.java @@ -20,7 +20,6 @@ import org.neo4j.graphdb.ConstraintViolationException; import org.neo4j.graphdb.NotFoundException; import org.neo4j.graphdb.NotInTransactionException; import org.neo4j.graphdb.TransactionFailureException; -import org.neo4j.index.impl.lucene.QueryNotPossibleException; import org.neo4j.kernel.DeadlockDetectedException; import org.neo4j.kernel.impl.locking.community.LockException; import org.neo4j.kernel.impl.transaction.IllegalResourceException; @@ -55,18 +54,19 @@ public class Neo4jExceptionTranslator implements PersistenceExceptionTranslator throw new InvalidDataAccessResourceUsageException(ire.getMessage(), ire); } catch(NotFoundException nfe) { throw new DataRetrievalFailureException(nfe.getMessage(), nfe); - } catch(QueryNotPossibleException qnpe) { - throw new ConcurrencyFailureException(qnpe.getMessage(),qnpe); } catch(DeadlockDetectedException dde) { throw new ConcurrencyFailureException(dde.getMessage(),dde); } catch(LockException le) { throw new ConcurrencyFailureException(le.getMessage(),le); } catch(RuntimeException e) { - if (e.getClass().getName().equals("org.neo4j.kernel.impl.core.ReadOnlyDbException")) + String exceptionName = e.getClass().getName(); + if (exceptionName.equals("org.neo4j.index.impl.lucene.QueryNotPossibleException")) + throw new ConcurrencyFailureException(e.getMessage(),e); + if (exceptionName.equals("org.neo4j.kernel.impl.core.ReadOnlyDbException")) throw new InvalidDataAccessResourceUsageException(e.getMessage(), e); - if (e.getClass().getName().equals("org.neo4j.kernel.impl.nioneo.store.StoreFailureException")) + if (exceptionName.equals("org.neo4j.kernel.impl.nioneo.store.StoreFailureException")) throw new DataAccessResourceFailureException(e.getMessage(), e); - if (e.getClass().getName().equals("org.neo4j.kernel.impl.persistence.IdGenerationFailedException")) + if (exceptionName.equals("org.neo4j.kernel.impl.persistence.IdGenerationFailedException")) throw new NonTransientDataAccessResourceException(e.getMessage(), e); throw e; // exception thrown by the user } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/CypherQueryEngineImpl.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/CypherQueryEngineImpl.java index de851565d..296cd02d7 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/CypherQueryEngineImpl.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/CypherQueryEngineImpl.java @@ -65,6 +65,7 @@ public class CypherQueryEngineImpl implements CypherQueryEngine { private ExecutionResult parseAndExecuteQuery(String statement, Map params) { try { final Map queryParams = queryParams(params); + statement = addRulePlannerDueToBugInNeo4j22(statement); if (log.isDebugEnabled()) log.debug(String.format("Executing cypher query: %s params %s",statement,queryParams)); return executionEngine.execute(statement, queryParams); @@ -73,6 +74,11 @@ public class CypherQueryEngineImpl implements CypherQueryEngine { } } + private String addRulePlannerDueToBugInNeo4j22(String statement) { +// if (statement.substring(0,5).equalsIgnoreCase("START")) return "PLANNER RULE "+statement; + return statement; + } + private Map queryParams(Map params) { return queryParameterConverter.convert(params); } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/typerepresentation/AbstractIndexBasedTypeRepresentationStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/typerepresentation/AbstractIndexBasedTypeRepresentationStrategy.java index a8ea9524e..872c4bbd4 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/typerepresentation/AbstractIndexBasedTypeRepresentationStrategy.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/typerepresentation/AbstractIndexBasedTypeRepresentationStrategy.java @@ -16,6 +16,7 @@ package org.springframework.data.neo4j.support.typerepresentation; import org.neo4j.graphdb.Node; +import org.neo4j.graphdb.NotFoundException; import org.neo4j.graphdb.PropertyContainer; import org.neo4j.graphdb.index.Index; import org.neo4j.graphdb.index.IndexHits; @@ -89,7 +90,7 @@ public abstract class AbstractIndexBasedTypeRepresentationStrategy get(Object value) { try { return typesIndex.get(INDEX_KEY, indexValueForType(value)); - } catch(IllegalStateException ise) { + } catch(IllegalStateException | NotFoundException ise) { typesIndex=createTypesIndex(); return typesIndex.get(INDEX_KEY, indexValueForType(value)); } @@ -108,7 +109,7 @@ public abstract class AbstractIndexBasedTypeRepresentationStrategy index = graphDatabase.getIndex("node"); Node lookedUpNode= index.get( "name", "node1" ).getSingle(); assertThat("same node from index", lookedUpNode, is(node1)); diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/Neo4jTemplateApiTransactionTests.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/Neo4jTemplateApiTransactionTests.java index 64927ca09..78ebd8812 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/Neo4jTemplateApiTransactionTests.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/Neo4jTemplateApiTransactionTests.java @@ -19,12 +19,12 @@ package org.springframework.data.neo4j.template; import org.junit.*; import org.neo4j.graphdb.*; import org.neo4j.kernel.GraphDatabaseAPI; -import org.neo4j.kernel.impl.transaction.SpringTransactionManager; import org.neo4j.test.TestGraphDatabaseFactory; import org.springframework.dao.DataAccessException; import org.springframework.data.neo4j.core.GraphDatabase; import org.springframework.data.neo4j.model.Person; import org.springframework.data.neo4j.support.DelegatingGraphDatabase; +import org.springframework.data.neo4j.support.Neo4jEmbeddedTransactionManager; import org.springframework.data.neo4j.support.Neo4jTemplate; import org.springframework.data.neo4j.support.index.IndexType; import org.springframework.transaction.PlatformTransactionManager; @@ -102,7 +102,7 @@ public class Neo4jTemplateApiTransactionTests { } protected PlatformTransactionManager createTransactionManager() { - return new JtaTransactionManager(new SpringTransactionManager((GraphDatabaseAPI)graphDatabaseService)); + return new JtaTransactionManager(new Neo4jEmbeddedTransactionManager((GraphDatabaseAPI)graphDatabaseService)); } private void createData() { diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/NeoApiTests.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/NeoApiTests.java index e76767c6f..9bbab72bf 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/NeoApiTests.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/NeoApiTests.java @@ -20,12 +20,12 @@ import org.junit.After; import org.junit.Before; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.kernel.GraphDatabaseAPI; -import org.neo4j.kernel.impl.transaction.SpringTransactionManager; import org.neo4j.test.TestGraphDatabaseFactory; import org.springframework.core.convert.ConversionService; import org.springframework.data.neo4j.core.GraphDatabase; import org.springframework.data.neo4j.fieldaccess.Neo4jConversionServiceFactoryBean; import org.springframework.data.neo4j.support.DelegatingGraphDatabase; +import org.springframework.data.neo4j.support.Neo4jEmbeddedTransactionManager; import org.springframework.data.neo4j.support.Neo4jTemplate; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.jta.JtaTransactionManager; @@ -53,7 +53,7 @@ public abstract class NeoApiTests { protected PlatformTransactionManager createTransactionManager() { - return new JtaTransactionManager(new SpringTransactionManager((GraphDatabaseAPI)graphDatabaseService)); + return new JtaTransactionManager(new Neo4jEmbeddedTransactionManager(graphDatabaseService)); } protected GraphDatabase createGraphDatabase() throws Exception diff --git a/spring-data-neo4j/template.mf b/spring-data-neo4j/template.mf index b6db9cdec..a1cfcfb3b 100644 --- a/spring-data-neo4j/template.mf +++ b/spring-data-neo4j/template.mf @@ -2,6 +2,8 @@ Bundle-SymbolicName: org.springframework.data.neo4j Bundle-Name: Spring Data Neo4J Bundle-Vendor: SpringSource Bundle-ManifestVersion: 2 +Export-Template: + org.springframework.data.neo4j.*;version="${project.version}" Import-Template: org.springframework.beans.*;version="[3.0.0, 4.0.0)", org.springframework.context.*;version="[3.0.0, 4.0.0)",