From aaef3b62aae0518521ef718b1f35da3086b212a4 Mon Sep 17 00:00:00 2001 From: Michael Hunger Date: Thu, 14 Apr 2011 12:09:19 +0200 Subject: [PATCH] added tests for server plugin support added tests for multiple index addition of an entity --- .../neo4j/rest/support/RestTestBase.java | 9 +-- .../neo4j/rest/support/ServerPluginTest.java | 74 ++++++++++++++++++ .../neo4j/rest/support/TestServerPlugin.java | 75 +++++++++++++++++++ .../org.neo4j.server.plugins.ServerPlugin | 1 + .../src/test/resources/Plugin-context.xml | 22 ++++++ ...gPropertyFieldAccessorListenerFactory.java | 16 ++-- ...rovidedClassPathXmlApplicationContext.java | 2 +- .../data/graph/neo4j/support/IndexTest.java | 45 ++++++++++- 8 files changed, 230 insertions(+), 14 deletions(-) create mode 100644 spring-data-neo4j-rest/src/test/java/org/springframework/data/graph/neo4j/rest/support/ServerPluginTest.java create mode 100644 spring-data-neo4j-rest/src/test/java/org/springframework/data/graph/neo4j/rest/support/TestServerPlugin.java create mode 100644 spring-data-neo4j-rest/src/test/resources/META-INF/services/org.neo4j.server.plugins.ServerPlugin create mode 100644 spring-data-neo4j-rest/src/test/resources/Plugin-context.xml diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/graph/neo4j/rest/support/RestTestBase.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/graph/neo4j/rest/support/RestTestBase.java index 0c19a74e1..9e63163e5 100644 --- a/spring-data-neo4j-rest/src/test/java/org/springframework/data/graph/neo4j/rest/support/RestTestBase.java +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/graph/neo4j/rest/support/RestTestBase.java @@ -26,16 +26,15 @@ import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Relationship; import java.net.URI; -import java.net.URISyntaxException; import java.util.Iterator; public class RestTestBase { protected RestGraphDatabase graphDb; private static final String HOSTNAME = "localhost"; - private static final int PORT = 7473; - private static LocalTestServer neoServer = new LocalTestServer(HOSTNAME,PORT).withPropertiesFile("test-db.properties"); - private static final String SERVER_ROOT_URI = "http://" + HOSTNAME + ":" + PORT + "/db/data/"; + public static final int PORT = 7473; + protected static LocalTestServer neoServer = new LocalTestServer(HOSTNAME,PORT).withPropertiesFile("test-db.properties"); + public static final String SERVER_ROOT_URI = "http://" + HOSTNAME + ":" + PORT + "/db/data/"; @BeforeClass public static void startDb() throws Exception { @@ -44,7 +43,7 @@ public class RestTestBase { } @Before - public void setUp() throws URISyntaxException { + public void setUp() throws Exception { cleanDb(); graphDb = new RestGraphDatabase(new URI(SERVER_ROOT_URI)); } diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/graph/neo4j/rest/support/ServerPluginTest.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/graph/neo4j/rest/support/ServerPluginTest.java new file mode 100644 index 000000000..74f093f86 --- /dev/null +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/graph/neo4j/rest/support/ServerPluginTest.java @@ -0,0 +1,74 @@ +/** + * 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.graph.neo4j.rest.support; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import org.codehaus.jackson.map.ObjectMapper; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.data.graph.neo4j.Person; +import org.springframework.data.graph.neo4j.server.ProvidedClassPathXmlApplicationContext; + +import javax.ws.rs.core.MediaType; +import java.io.IOException; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.springframework.data.graph.neo4j.Person.persistedPerson; + +/** + * @author mh + * @since 14.04.11 + */ +public class ServerPluginTest extends RestTestBase { + + private Person person; + + @BeforeClass + public static void init() { + new ProvidedClassPathXmlApplicationContext(neoServer.getGraphDatabase(), "Plugin-context.xml"); + } + + @Override + public void setUp() throws Exception { + super.setUp(); + person = persistedPerson("Michael", 35); + } + + @Test + public void testGetFriends() throws IOException { + final ClientResponse response = createRequest("ext/TestServerPlugin/graphdb/person").post(ClientResponse.class, "{\"name\":\"" + person.getName() + "\"}"); + assertEquals(200,response.getStatus()); + final String result = response.getEntity(String.class); + final Map data = (Map) new ObjectMapper().readValue(result, Object.class); + assertEquals(person.getName(),((Map)data.get("data")).get("Person.name")); + + } + + private ClientResponse post(String uriSuffix, String params) { + return createRequest(uriSuffix).post(ClientResponse.class, params); + } + + private static WebResource.Builder createRequest(String uriSuffix) { + return Client.create(). + resource(SERVER_ROOT_URI + uriSuffix). + type(MediaType.APPLICATION_JSON). + accept(MediaType.APPLICATION_JSON); + } +} diff --git a/spring-data-neo4j-rest/src/test/java/org/springframework/data/graph/neo4j/rest/support/TestServerPlugin.java b/spring-data-neo4j-rest/src/test/java/org/springframework/data/graph/neo4j/rest/support/TestServerPlugin.java new file mode 100644 index 000000000..2132331c4 --- /dev/null +++ b/spring-data-neo4j-rest/src/test/java/org/springframework/data/graph/neo4j/rest/support/TestServerPlugin.java @@ -0,0 +1,75 @@ +/** + * 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.graph.neo4j.rest.support; + +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Node; +import org.neo4j.helpers.collection.IterableWrapper; +import org.neo4j.server.plugins.*; +import org.springframework.context.ApplicationContext; +import org.springframework.data.graph.neo4j.Friendship; +import org.springframework.data.graph.neo4j.Person; +import org.springframework.data.graph.neo4j.PersonRepository; +import org.springframework.data.graph.neo4j.server.ProvidedClassPathXmlApplicationContext; +import org.springframework.data.graph.neo4j.support.GraphDatabaseContext; + +/** + * @author mh + * @since 14.04.11 + */ +@Description("A test plugin for spring data graph usage") +public class TestServerPlugin extends ServerPlugin { + + private ApplicationContext ctx; + private PersonRepository personRepository; + private GraphDatabaseContext graphDatabaseContext; + + public TestServerPlugin() { + System.out.println("Initializing ServerPlugin"); + } + + @Name( "person") + @PluginTarget(GraphDatabaseService.class) + public Node person(@Source GraphDatabaseService graphDb, @Parameter(name="name") String name) { + context(graphDb); + final Person result = personRepository.findByPropertyValue(Person.NAME_INDEX, "Person.name",name); + return result!=null ? result.getPersistentState() : null; + } + + private synchronized ApplicationContext context(GraphDatabaseService graphDb) { + if (ctx==null) { + ctx = new ProvidedClassPathXmlApplicationContext(graphDb, "Plugin-context.xml"); + personRepository = ctx.getBean(PersonRepository.class); + graphDatabaseContext = ctx.getBean(GraphDatabaseContext.class); + } + return ctx; + } + + @Name( "get_all_friends" ) + @Description("gets all friends of the given node") + @PluginTarget(Node.class) + public Iterable allFriendsOf(@Source Node target) { + context(target.getGraphDatabase()); + final Person person = graphDatabaseContext.createEntityFromState(target, Person.class); + return new IterableWrapper(person.getFriendships()) { + @Override + protected Node underlyingObjectToObject(Friendship friendship) { + return friendship.getPerson2().getPersistentState(); + } + }; + } +} diff --git a/spring-data-neo4j-rest/src/test/resources/META-INF/services/org.neo4j.server.plugins.ServerPlugin b/spring-data-neo4j-rest/src/test/resources/META-INF/services/org.neo4j.server.plugins.ServerPlugin new file mode 100644 index 000000000..55a834ac8 --- /dev/null +++ b/spring-data-neo4j-rest/src/test/resources/META-INF/services/org.neo4j.server.plugins.ServerPlugin @@ -0,0 +1 @@ +org.springframework.data.graph.neo4j.rest.support.TestServerPlugin diff --git a/spring-data-neo4j-rest/src/test/resources/Plugin-context.xml b/spring-data-neo4j-rest/src/test/resources/Plugin-context.xml new file mode 100644 index 000000000..f217d36a4 --- /dev/null +++ b/spring-data-neo4j-rest/src/test/resources/Plugin-context.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/IndexingPropertyFieldAccessorListenerFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/IndexingPropertyFieldAccessorListenerFactory.java index 10163c225..62aa179f8 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/IndexingPropertyFieldAccessorListenerFactory.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/IndexingPropertyFieldAccessorListenerFactory.java @@ -21,7 +21,6 @@ import org.apache.commons.logging.LogFactory; import org.neo4j.graphdb.PropertyContainer; import org.neo4j.graphdb.index.Index; import org.neo4j.index.lucene.ValueContext; -import org.springframework.data.graph.annotation.NodeEntity; import org.springframework.data.graph.core.GraphBacked; import org.springframework.data.graph.neo4j.annotation.Indexed; import org.springframework.data.graph.neo4j.support.GraphDatabaseContext; @@ -61,7 +60,7 @@ public class IndexingPropertyFieldAccessorListenerFactory graphBacked = (Class) field.getDeclaringClass(); Index index = getIndex(field,graphBacked); String indexKey = getIndexKey(field); - return (FieldAccessListener) new IndexingPropertyFieldAccessorListener(field, index, indexKey); + return (FieldAccessListener) new IndexingPropertyFieldAccessorListener(index, indexKey); } private String getIndexKey(Field field) { @@ -101,7 +100,7 @@ public class IndexingPropertyFieldAccessorListenerFactory index; - public IndexingPropertyFieldAccessorListener(final Field field, final Index index, final String indexKey) { + public IndexingPropertyFieldAccessorListener(final Index index, final String indexKey) { this.index = index; this.indexKey = indexKey; } @@ -110,8 +109,13 @@ public class IndexingPropertyFieldAccessorListenerFactory graphBacked, Object oldVal, Object newVal) { if (newVal instanceof Number) newVal = ValueContext.numeric((Number) newVal); - if (newVal==null) index.remove(graphBacked.getPersistentState(), indexKey, null); - else index.add(graphBacked.getPersistentState(), indexKey, newVal); - } + final T state = graphBacked.getPersistentState(); + //index.remove(state, indexKey); + if (newVal == null) { + index.remove(state, indexKey); + } else { + index.add(state, indexKey, newVal); + } + } } } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/server/ProvidedClassPathXmlApplicationContext.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/server/ProvidedClassPathXmlApplicationContext.java index 4207e4ba3..9cdf407c7 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/server/ProvidedClassPathXmlApplicationContext.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/server/ProvidedClassPathXmlApplicationContext.java @@ -28,7 +28,7 @@ public class ProvidedClassPathXmlApplicationContext extends ClassPathXmlApplicat private final GraphDatabaseService database; - public ProvidedClassPathXmlApplicationContext(GraphDatabaseService database, final String[] locations) + public ProvidedClassPathXmlApplicationContext(GraphDatabaseService database, final String... locations) throws org.springframework.beans.BeansException { super(); setConfigLocations(locations); diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/IndexTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/IndexTest.java index 259adaf6f..45d58c642 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/IndexTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/graph/neo4j/support/IndexTest.java @@ -45,6 +45,7 @@ import java.util.Collection; import java.util.HashSet; import static org.junit.Assert.*; +import static org.springframework.data.graph.neo4j.Person.NAME_INDEX; import static org.springframework.data.graph.neo4j.Person.persistedPerson; @RunWith(SpringJUnit4ClassRunner.class) @@ -95,7 +96,7 @@ public class IndexTest { Person me = persistedPerson(NAME_VALUE, 35); Person spouse = persistedPerson(NAME_VALUE3, 36); me.setSpouse(spouse); - final Person foundMe = this.personRepository.findByPropertyValue(Person.NAME_INDEX, "Person.name", NAME_VALUE); + final Person foundMe = this.personRepository.findByPropertyValue(NAME_INDEX, "Person.name", NAME_VALUE); assertEquals(spouse, foundMe.getSpouse()); } @@ -241,7 +242,7 @@ public class IndexTest { @Transactional public void testFindAllPersonByIndexOnAnnotatedField() { Person person = persistedPerson(NAME_VALUE, 35); - final Person found = personRepository.findByPropertyValue(Person.NAME_INDEX, "Person.name", NAME_VALUE); + final Person found = personRepository.findByPropertyValue(NAME_INDEX, "Person.name", NAME_VALUE); assertEquals(person, found); } @@ -288,6 +289,46 @@ public class IndexTest { Assert.assertEquals("indexed node found", node, nodeIndex.get(NAME, NAME_VALUE).next()); } + @Test + @Transactional + public void testNodeCanbBeIndexedTwice() { + final Person p = persistedPerson(NAME_VALUE2, 30); + Assert.assertEquals(p, personRepository.findByPropertyValue(NAME_INDEX, "Person.name", NAME_VALUE2)); + p.setName(NAME_VALUE); + Assert.assertEquals(p, personRepository.findByPropertyValue(NAME_INDEX, "Person.name", NAME_VALUE)); + p.setName(NAME_VALUE2); + Assert.assertEquals(p, personRepository.findByPropertyValue(NAME_INDEX, "Person.name", NAME_VALUE2)); + } + @Test + public void testNodeCanbBeIndexedTwiceInDifferentTransactions() { + Transaction tx = null; + final Person p; + try { + tx = graphDatabaseContext.beginTx(); + p = persistedPerson(NAME_VALUE2, 30); + tx.success(); + } finally { + tx.finish(); + } + Assert.assertEquals(p, personRepository.findByPropertyValue(NAME_INDEX, "Person.name", NAME_VALUE2)); + try { + tx = graphDatabaseContext.beginTx(); + p.setName(NAME_VALUE); + tx.success(); + } finally { + tx.finish(); + } + Assert.assertEquals(p, personRepository.findByPropertyValue(NAME_INDEX, "Person.name", NAME_VALUE)); + try { + tx = graphDatabaseContext.beginTx(); + p.setName(NAME_VALUE2); + tx.success(); + } finally { + tx.finish(); + } + Assert.assertEquals(p, personRepository.findByPropertyValue(NAME_INDEX, "Person.name", NAME_VALUE2)); + } + @Test @Transactional public void testRelationshipIsIndexed() {