diff --git a/spring-data-neo4j-cross-store/src/main/java/org/springframework/data/neo4j/cross_store/config/CrossStoreNeo4jConfiguration.java b/spring-data-neo4j-cross-store/src/main/java/org/springframework/data/neo4j/cross_store/config/CrossStoreNeo4jConfiguration.java
index 5ab08faa3..57b219b2a 100644
--- a/spring-data-neo4j-cross-store/src/main/java/org/springframework/data/neo4j/cross_store/config/CrossStoreNeo4jConfiguration.java
+++ b/spring-data-neo4j-cross-store/src/main/java/org/springframework/data/neo4j/cross_store/config/CrossStoreNeo4jConfiguration.java
@@ -15,11 +15,13 @@
*/
package org.springframework.data.neo4j.cross_store.config;
+import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
import org.springframework.data.neo4j.aspects.config.Neo4jAspectConfiguration;
import org.springframework.data.neo4j.config.JtaTransactionManagerFactoryBean;
import org.springframework.data.neo4j.cross_store.support.node.CrossStoreNodeDelegatingFieldAccessorFactory;
@@ -69,8 +71,8 @@ public class CrossStoreNeo4jConfiguration extends Neo4jAspectConfiguration {
}
@Bean
- public PlatformTransactionManager neo4jTransactionManager() throws Exception {
- JtaTransactionManager jtaTm = new JtaTransactionManagerFactoryBean( getGraphDatabaseService() ).getObject();
+ public PlatformTransactionManager neo4jTransactionManager(GraphDatabaseService graphDatabaseService) {
+ JtaTransactionManager jtaTm = new JtaTransactionManagerFactoryBean( graphDatabaseService ).getObject();
if (isUsingCrossStorePersistence()) {
JpaTransactionManager jpaTm = new JpaTransactionManager(getEntityManagerFactory());
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
new file mode 100644
index 000000000..6ea295d97
--- /dev/null
+++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/CypherRestGraphDatabase.java
@@ -0,0 +1,170 @@
+/**
+ * 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.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;
+import org.neo4j.rest.graphdb.traversal.RestTraversalDescription;
+import org.neo4j.rest.graphdb.util.ResourceIterableWrapper;
+
+import javax.transaction.SystemException;
+import javax.transaction.TransactionManager;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+
+public class CypherRestGraphDatabase extends AbstractRemoteDatabase {
+ private RestAPICypherImpl restAPI;
+
+ public CypherRestGraphDatabase(RestAPI restAPI){
+ this.restAPI = new RestAPICypherImpl(restAPI);
+ }
+
+ public CypherRestGraphDatabase(String uri) {
+ this( new RestAPIImpl( uri ));
+ }
+
+ public CypherRestGraphDatabase(String uri, String user, String password) {
+ this(new RestAPIImpl( uri, user, password ));
+ }
+
+ public RestAPI getRestAPI(){
+ return this.restAPI;
+ }
+
+ public RestIndexManager index() {
+ return this.restAPI.index();
+ }
+
+ public Node createNode() {
+ return this.restAPI.createNode(null);
+ }
+
+ public Node getNodeById( long id ) {
+ return this.restAPI.getNodeById(id);
+ }
+
+ @Override
+ public Iterable getAllNodes() {
+ return restAPI.getAllNodes();
+ }
+
+ @Override
+ public Iterable getRelationshipTypes() {
+ return this.restAPI.getRelationshipTypes();
+ }
+
+ 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;
+ }
+
+ public RestCypherTransactionManager getTxManager() {
+ return restAPI.getTxManager();
+ }
+
+ @Override
+ public DependencyResolver getDependencyResolver() {
+ return new DependencyResolver.Adapter() {
+ @Override
+ public T resolveDependency(Class type, SelectionStrategy selector) throws IllegalArgumentException {
+ if (TransactionManager.class.isAssignableFrom(type)) return (T)getTxManager();
+ return null;
+ }
+ };
+ }
+
+ @Override
+ public Transaction beginTx() {
+ return restAPI.beginTx();
+ }
+
+ @Override
+ public void shutdown() {
+ try {
+ getTxManager().rollback();
+ } catch (SystemException e) {
+ // ignore
+ }
+ restAPI.close();
+ }
+
+ @Override
+ public Node createNode(Label... labels) {
+ return restAPI.createNode(null, toLabelNames(labels));
+ }
+
+ public Set toLabelNames(Label[] labels) {
+ Set labelNames = new LinkedHashSet<>(labels.length);
+ for (Label label : labels) labelNames.add(label.name());
+ return labelNames;
+ }
+
+ @Override
+ public ResourceIterable findNodesByLabelAndProperty(Label label, String property, Object value) {
+ Iterable nodes = restAPI.getNodesByLabelAndProperty(label.name(), property, value);
+ return new ResourceIterableWrapper(nodes) {
+ protected Node underlyingObjectToObject(RestNode node) {
+ return node;
+ }
+ };
+ }
+
+ @Override
+ public Schema schema() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public RestTraversalDescription traversalDescription() {
+ return restAPI.createTraversalDescription();
+ }
+
+ @Override
+ public BidirectionalTraversalDescription bidirectionalTraversalDescription() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Collection getAllLabelNames() {
+ return restAPI.getAllLabelNames();
+ }
+}
+
diff --git a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestAPI.java b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestAPI.java
index 120192a0d..4bb3a2da3 100644
--- a/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestAPI.java
+++ b/spring-data-neo4j-rest/src/main/java/org/neo4j/rest/graphdb/RestAPI.java
@@ -25,6 +25,7 @@ import org.neo4j.rest.graphdb.query.CypherRestResult;
import org.neo4j.rest.graphdb.entity.RestEntity;
import org.neo4j.rest.graphdb.entity.RestNode;
import org.neo4j.rest.graphdb.entity.RestRelationship;
+import org.neo4j.rest.graphdb.traversal.RestTraversalDescription;
import org.neo4j.rest.graphdb.traversal.RestTraverser;
import org.neo4j.rest.graphdb.util.QueryResult;
import org.neo4j.rest.graphdb.util.ResultConverter;
@@ -71,7 +72,7 @@ public interface RestAPI extends RestAPIIndex, RestAPIInternal {
Iterable getRelationshipTypes();
- TraversalDescription createTraversalDescription();
+ RestTraversalDescription createTraversalDescription();
Iterable getRelationships(RestNode restNode, Direction direction, RelationshipType... types);
@@ -87,6 +88,7 @@ public interface RestAPI extends RestAPIIndex, RestAPIInternal {
RestNode addToCache(RestNode restNode);
RestNode getFromCache(long id);
+ void removeFromCache(long id);
void close();
}
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 b5f16f5c5..55811c4fb 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
@@ -33,13 +33,12 @@ import org.neo4j.rest.graphdb.entity.RestRelationship;
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.CypherResult;
-import org.neo4j.rest.graphdb.query.CypherTransaction;
-import org.neo4j.rest.graphdb.query.CypherTxResult;
-import org.neo4j.rest.graphdb.query.RestQueryResult;
+import org.neo4j.rest.graphdb.query.*;
import org.neo4j.rest.graphdb.transaction.RemoteCypherTransaction;
+import org.neo4j.rest.graphdb.traversal.RestTraversalDescription;
import org.neo4j.rest.graphdb.traversal.RestTraverser;
import org.neo4j.rest.graphdb.util.QueryResult;
+import org.neo4j.rest.graphdb.util.QueryResultBuilder;
import org.neo4j.rest.graphdb.util.ResultConverter;
import javax.ws.rs.core.Response.Status;
@@ -52,7 +51,11 @@ public class RestAPICypherImpl implements RestAPI {
public static final String _QUERY_RETURN_NODE = " RETURN id(n) as id, labels(n) as labels, n as data";
public static final String _QUERY_RETURN_REL = " RETURN id(r) as id, type(r) as type, r as data, id(startNode(r)) as start, id(endNode(r)) as end";
- public static String MATCH_NODE_QUERY(String name) { return " MATCH ("+name+") WHERE id("+name+") = {id_"+name+"} "; }
+
+ public static String MATCH_NODE_QUERY(String name) {
+ return " MATCH (" + name + ") WHERE id(" + name + ") = {id_" + name + "} ";
+ }
+
public static final String _MATCH_NODE_QUERY = " MATCH (n) WHERE id(n) = {id} ";
public static final String GET_NODE_QUERY = _MATCH_NODE_QUERY + _QUERY_RETURN_NODE;
public static final String _MATCH_REL_QUERY = " START r=rel({id}) ";
@@ -67,17 +70,17 @@ public class RestAPICypherImpl implements RestAPI {
private String mergeQuery(String labelName, String key, Collection labels) {
StringBuilder setLabels = new StringBuilder();
- if (labels!=null) {
+ if (labels != null) {
for (String label : labels) {
if (label.equals(labelName)) continue;
setLabels.append("SET n:").append(label).append(" ");
}
}
- return "MERGE (n:`"+labelName+"` {`"+key+"`: {value}}) ON CREATE SET n={props} "+setLabels+ _QUERY_RETURN_NODE;
+ return "MERGE (n:`" + labelName + "` {`" + key + "`: {value}}) ON CREATE SET n={props} " + setLabels + _QUERY_RETURN_NODE;
}
private String toLabelString(Collection labels) {
- if (labels==null || labels.size() == 0) return "";
+ if (labels == null || labels.size() == 0) return "";
StringBuilder sb = new StringBuilder();
for (String label : labels) {
sb.append(":").append(label);
@@ -86,13 +89,11 @@ public class RestAPICypherImpl implements RestAPI {
}
private final RestAPI restAPI;
- private RestRequest restRequest;
- private static final ThreadLocal cypherTransaction = new ThreadLocal<>();
+ private final RestCypherTransactionManager txManager = new RestCypherTransactionManager(this);
protected RestAPICypherImpl(RestAPI restAPI) {
this.restAPI = restAPI;
- this.restRequest = restAPI.getRestRequest();
}
@Override
@@ -101,7 +102,7 @@ public class RestAPICypherImpl implements RestAPI {
RestNode restNode = getFromCache(id);
if (restNode != null) return restNode;
}
- if (force == Load.FromCache) return new RestNode(RestNode.nodeUri(this, id),this);
+ if (force == Load.FromCache) return new RestNode(RestNode.nodeUri(this, id), this);
Iterator> result = query(GET_NODE_QUERY, map("id", id)).getData().iterator();
if (!result.hasNext()) {
throw new NotFoundException("Node not found " + id);
@@ -114,6 +115,11 @@ public class RestAPICypherImpl implements RestAPI {
return restAPI.getFromCache(id);
}
+ @Override
+ public void removeFromCache(long id) {
+ restAPI.removeFromCache(id);
+ }
+
@Override
public RestNode getNodeById(long id) {
return getNodeById(id, Load.FromServer);
@@ -122,34 +128,44 @@ public class RestAPICypherImpl implements RestAPI {
private RestNode toNode(List