diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryMapResulConverter.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryMapResulConverter.java index c7e5a5b9f..da6b13562 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryMapResulConverter.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryMapResulConverter.java @@ -16,6 +16,7 @@ package org.springframework.data.neo4j.conversion; import org.springframework.data.neo4j.annotation.ResultColumn; +import org.springframework.data.neo4j.support.conversion.NoSuchColumnFoundException; import org.springframework.data.neo4j.template.Neo4jOperations; import org.springframework.data.util.ClassTypeInformation; import org.springframework.data.util.TypeInformation; @@ -42,7 +43,14 @@ public class QueryMapResulConverter implements ResultConverter returnType = ClassTypeInformation.fromReturnTypeOf(method); - Object columnValue = valueCopy.get(column.value()); + + String columnName = column.value(); + if(!valueCopy.containsKey( columnName )) { + throw new NoSuchColumnFoundException( columnName ); + } + + Object columnValue = valueCopy.get( columnName ); + Object result; if (returnType.isCollectionLike()) diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/EntityResultConverter.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/EntityResultConverter.java index f76d59fda..cc3b48acd 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/EntityResultConverter.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/EntityResultConverter.java @@ -99,7 +99,13 @@ public class EntityResultConverter extends DefaultConverter { public Object invoke(Object o, Method method, Object[] objects) throws Throwable { ResultColumn column = method.getAnnotation(ResultColumn.class); TypeInformation returnType = ClassTypeInformation.fromReturnTypeOf(method); - Object columnValue = map.get(column.value()); + + String columnName = column.value(); + if(!map.containsKey( columnName )) { + throw new NoSuchColumnFoundException( columnName ); + } + + Object columnValue = map.get( columnName ); if(columnValue==null) return null; // If the returned value is a Scala iterable, transform it to a Java iterable first diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/NoSuchColumnFoundException.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/NoSuchColumnFoundException.java new file mode 100644 index 000000000..a5aee33d2 --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/NoSuchColumnFoundException.java @@ -0,0 +1,24 @@ +/** + * 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.support.conversion; + +import org.springframework.data.mapping.model.MappingException; + +public class NoSuchColumnFoundException extends MappingException { + public NoSuchColumnFoundException( String column ) { + super( "Expexted a column named "+ column + " to be in the result set." ); + } +} diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/conversion/QueryMapResultConverterTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/conversion/QueryMapResultConverterTest.java index 6be423898..b5f49e19f 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/conversion/QueryMapResultConverterTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/conversion/QueryMapResultConverterTest.java @@ -21,6 +21,7 @@ import org.springframework.data.neo4j.annotation.ResultColumn; import org.springframework.data.neo4j.mapping.Neo4jPersistentTestBase; import org.springframework.data.neo4j.model.Friendship; import org.springframework.data.neo4j.model.Person; +import org.springframework.data.neo4j.support.conversion.NoSuchColumnFoundException; import java.util.List; import java.util.Map; @@ -40,67 +41,76 @@ public class QueryMapResultConverterTest extends Neo4jPersistentTestBase { private Map advancedMap; public interface PersonAndFriendsData { - @ResultColumn("person") + @ResultColumn( "person" ) Person getPerson(); - @ResultColumn("collect(r)") + @ResultColumn( "collect(r)" ) Iterable getFriends(); } public interface SimplestQuery { - @ResultColumn("name") + @ResultColumn( "name" ) String getName(); - @ResultColumn("age") + @ResultColumn( "age" ) Integer getAge(); - @ResultColumn("friends") + @ResultColumn( "friends" ) Iterable getFriendNames(); } @Before public void init() throws Exception { - storeInGraph(michael); - storeInGraph(andres); - storeInGraph(emil); + storeInGraph( michael ); + storeInGraph( andres ); + storeInGraph( emil ); - makeFriends(michaelNode(), andresNode(), 19); - makeFriends(michaelNode(), emilNode(), 6); + makeFriends( michaelNode(), andresNode(), 19 ); + makeFriends( michaelNode(), emilNode(), 6 ); - friends = asList("Michael", "Emil", "Anders"); - simpleMap = map("name", "Andres", "age", 36L, "friends", friends); - advancedMap = map("person", michaelNode(), "collect(r)", michaelNode().getRelationships(KNOWS)); + friends = asList( "Michael", "Emil", "Anders" ); + simpleMap = map( "name", "Andres", "age", 36L, "friends", friends ); + advancedMap = map( "person", michaelNode(), "collect(r)", michaelNode().getRelationships( KNOWS ) ); - michael = readPerson(michaelNode()); + michael = readPerson( michaelNode() ); } @Test public void shouldBeAbleToGetAStringFromAResultMap() throws Exception { QueryMapResulConverter converter = getConverter(); - SimplestQuery query = converter.convert(simpleMap, SimplestQuery.class); + SimplestQuery query = converter.convert( simpleMap, SimplestQuery.class ); - assertThat(query.getName(), equalTo("Andres")); - assertThat(query.getAge(), equalTo(36)); + assertThat( query.getName(), equalTo( "Andres" ) ); + assertThat( query.getAge(), equalTo( 36 ) ); } @Test public void shouldBeAbleToHandleAnIterableOfString() throws Exception { QueryMapResulConverter converter = getConverter(); - SimplestQuery query = converter.convert(simpleMap, SimplestQuery.class); + SimplestQuery query = converter.convert( simpleMap, SimplestQuery.class ); - assertThat(query.getFriendNames(), hasItems("Michael", "Emil", "Anders")); + assertThat( query.getFriendNames(), hasItems( "Michael", "Emil", "Anders" ) ); } @Test public void shouldHandleANodeBackedEntity() throws Exception { - QueryMapResulConverter converter = new QueryMapResulConverter(template); - PersonAndFriendsData result = converter.convert(advancedMap, PersonAndFriendsData.class); + QueryMapResulConverter converter = new QueryMapResulConverter( + template ); + PersonAndFriendsData result = converter.convert( advancedMap, PersonAndFriendsData.class ); - assertThat(result.getPerson(), equalTo(michael)); - assertThat(asCollection(result.getFriends()), equalTo(asCollection(michael.getFriendships()))); + assertThat( result.getPerson(), equalTo( michael ) ); + assertThat( asCollection( result.getFriends() ), equalTo( asCollection( michael.getFriendships() ) ) ); + } + + @Test( expected = NoSuchColumnFoundException.class ) + public void shouldThrowNiceException() throws Exception { + QueryMapResulConverter converter = new QueryMapResulConverter( + template ); + PersonAndFriendsData convert = converter.convert( map(), PersonAndFriendsData.class ); + convert.getFriends(); } private QueryMapResulConverter getConverter() { - return new QueryMapResulConverter(template); + return new QueryMapResulConverter( template ); } } \ No newline at end of file diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/GraphRepositoryTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/GraphRepositoryTest.java index d7322447d..9c8ab4df1 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/GraphRepositoryTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/GraphRepositoryTest.java @@ -28,6 +28,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.neo4j.model.Group; import org.springframework.data.neo4j.model.Person; import org.springframework.data.neo4j.support.Neo4jTemplate; +import org.springframework.data.neo4j.support.conversion.NoSuchColumnFoundException; import org.springframework.data.neo4j.support.node.Neo4jHelper; import org.springframework.test.context.CleanContextCacheTestExecutionListener; import org.springframework.test.context.ContextConfiguration; @@ -45,6 +46,7 @@ import static java.util.Arrays.asList; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; import static org.junit.internal.matchers.IsCollectionContaining.hasItem; import static org.junit.internal.matchers.IsCollectionContaining.hasItems; import static org.neo4j.helpers.collection.IteratorUtil.addToCollection; @@ -79,13 +81,13 @@ public class GraphRepositoryTest { @Before public void setUp() throws Exception { testTeam = new TestTeam(); - testTeam.createSDGTeam(personRepository, groupRepository, friendshipRepository); + testTeam.createSDGTeam( personRepository, groupRepository, friendshipRepository ); } @Test public void testFindIterableOfPersonWithQueryAnnotation() { Iterable teamMembers = personRepository.findAllTeamMembers(testTeam.sdg); - assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david, testTeam.emil)); + assertThat( asCollection( teamMembers ), hasItems( testTeam.michael, testTeam.david, testTeam.emil ) ); } @Test @@ -93,23 +95,23 @@ public class GraphRepositoryTest { Iterable teamMembers = personRepository.findWithinBoundingBox("personLayer", 55, 15, 57, 17); assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david)); } - + @Test public void testFindIterableOfPersonWithQueryAnnotationAndGremlin() { - Iterable teamMembers = personRepository.findAllTeamMembersGremlin(testTeam.sdg); - assertThat(asCollection(teamMembers), hasItems(testTeam.michael, testTeam.david, testTeam.emil)); + Iterable teamMembers = personRepository.findAllTeamMembersGremlin( testTeam.sdg ); + assertThat( asCollection( teamMembers ), hasItems( testTeam.michael, testTeam.david, testTeam.emil ) ); } @Test public void testFindPersonWithQueryAnnotation() { - Person boss = personRepository.findBoss(testTeam.michael); - assertThat(boss, is(testTeam.emil)); + Person boss = personRepository.findBoss( testTeam.michael ); + assertThat(boss, is( testTeam.emil )); } @Test public void testFindPersonWithQueryAnnotationUsingLongAsParameter() { - Person boss = personRepository.findBoss(testTeam.michael.getId()); - assertThat(boss, is(testTeam.emil)); + Person boss = personRepository.findBoss( testTeam.michael.getId() ); + assertThat(boss, is( testTeam.emil )); } @Test @@ -173,4 +175,10 @@ public class GraphRepositoryTest { Iterable findByName = personRepository.findByName(testTeam.michael.getName()); assertThat(findByName, hasItem(testTeam.michael)); } + + @Test( expected = NoSuchColumnFoundException.class) + public void missingColumnIsReportedNicely() { + Iterable findByName = personRepository.nonWorkingQuery( testTeam.michael ); + Person boss = findByName.iterator().next().getBoss(); + } } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/PersonRepository.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/PersonRepository.java index f2f612dc8..f89dd0960 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/PersonRepository.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/repository/PersonRepository.java @@ -48,6 +48,10 @@ public interface PersonRepository extends GraphRepository, NamedIndexRep @Query("start member=node({p_person}) match team-[:persons]->member<-[?:boss]-boss return collect(team), boss") Iterable findMemberData(@Param("p_person") Person person); + @Query("start member=node({p_person}) match team-[:persons]->member<-[?:boss]-boss return member") + Iterable nonWorkingQuery(@Param("p_person") Person person); + + @Query("start person=node({p_person}) match (boss)-[:boss]->(person) return boss") Person findBoss(@Param("p_person") Person person);