diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java
index 70c155e09..88381f3ac 100644
--- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java
+++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryPropertyReferenceController.java
@@ -179,6 +179,7 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes
return null;
}
};
+
try {
doWithReferencedProperty(repoRequest, id, property, handler);
} catch (IllegalArgumentException iae) {
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AbstractWebIntegrationTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AbstractWebIntegrationTests.java
index fbd590f52..cb2018589 100644
--- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AbstractWebIntegrationTests.java
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AbstractWebIntegrationTests.java
@@ -24,6 +24,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
+
+import net.minidev.json.JSONArray;
import org.junit.Before;
import org.junit.Test;
@@ -45,6 +48,8 @@ import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
import org.springframework.web.context.WebApplicationContext;
import com.jayway.jsonpath.JsonPath;
@@ -87,7 +92,11 @@ public abstract class AbstractWebIntegrationTests {
}
protected ResultActions follow(Link link) throws Exception {
- return mvc.perform(get(link.getHref()));
+ return follow(link.getHref());
+ }
+
+ protected ResultActions follow(String href) throws Exception {
+ return mvc.perform(get(href));
}
protected List discover(String rel) throws Exception {
@@ -270,9 +279,12 @@ public abstract class AbstractWebIntegrationTests {
for (String rel : expectedRootLinkRels()) {
Link link = assertHasLinkWithRel(rel, response);
- Link searchLink = assertHasLinkWithRel("search", request(link));
+ String rootResourceRepresentation = request(link).getContentAsString();
+ Link searchLink = getDiscoverer(response).findLinkWithRel("search", rootResourceRepresentation);
- request(searchLink);
+ if (searchLink != null) {
+ request(searchLink);
+ }
}
}
@@ -301,9 +313,42 @@ public abstract class AbstractWebIntegrationTests {
}
}
+ /**
+ * @see DATAREST-198
+ */
+ @Test
+ public void accessLinkedResources() throws Exception {
+
+ MockHttpServletResponse rootResource = request("/");
+
+ for (Entry> linked : getRootAndLinkedResources().entrySet()) {
+
+ Link resourceLink = assertHasLinkWithRel(linked.getKey(), rootResource);
+ MockHttpServletResponse resource = request(resourceLink);
+
+ for (String linkedRel : linked.getValue()) {
+
+ // Find URIs pointing to linked resources
+ String jsonPath = String.format("$..%s._links.%s.href", linked.getKey(), linkedRel);
+ String representation = resource.getContentAsString();
+ JSONArray uris = JsonPath.read(representation, jsonPath);
+
+ for (Object href : uris) {
+
+ follow(href.toString()). //
+ andExpect(status().isOk());
+ }
+ }
+ }
+ }
+
protected abstract Iterable expectedRootLinkRels();
protected Map getPayloadToPost() throws Exception {
return Collections.emptyMap();
}
+
+ protected MultiValueMap getRootAndLinkedResources() {
+ return new LinkedMultiValueMap(0);
+ }
}
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/Author.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/Author.java
new file mode 100644
index 000000000..017539610
--- /dev/null
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/Author.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 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.rest.webmvc.jpa;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+
+@Entity
+public class Author {
+
+ @Id @GeneratedValue//
+ Long id;
+ String name;
+
+ @ManyToMany(mappedBy = "authors")//
+ Set books = new HashSet();
+
+ protected Author() {}
+
+ public Author(String name) {
+ this.name = name;
+ }
+}
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/AuthorRepository.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/AuthorRepository.java
new file mode 100644
index 000000000..e30d94de1
--- /dev/null
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/AuthorRepository.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 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.rest.webmvc.jpa;
+
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * @author Oliver Gierke
+ */
+public interface AuthorRepository extends CrudRepository {
+
+}
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/Book.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/Book.java
new file mode 100644
index 000000000..ae6885c19
--- /dev/null
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/Book.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013 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.rest.webmvc.jpa;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+
+@Entity
+public class Book {
+
+ @Id String isbn;
+
+ @ManyToMany(cascade = { CascadeType.MERGE })//
+ Set authors;
+
+ String title;
+
+ protected Book() {}
+
+ public Book(String isbn, String title, Iterable authors) {
+
+ this.isbn = isbn;
+ this.title = title;
+
+ this.authors = new HashSet();
+
+ for (Author author : authors) {
+ author.books.add(this);
+ this.authors.add(author);
+ }
+ }
+}
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/BookRepository.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/BookRepository.java
new file mode 100644
index 000000000..2647cf7b8
--- /dev/null
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/BookRepository.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 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.rest.webmvc.jpa;
+
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * @author Oliver Gierke
+ */
+public interface BookRepository extends CrudRepository {
+
+}
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/JpaWebTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/JpaWebTests.java
index 989742070..0b92bd9c6 100644
--- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/JpaWebTests.java
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/JpaWebTests.java
@@ -38,6 +38,8 @@ import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
/**
@@ -71,7 +73,7 @@ public class JpaWebTests extends AbstractWebIntegrationTests {
*/
@Override
protected Iterable expectedRootLinkRels() {
- return Arrays.asList("people");
+ return Arrays.asList("people", "authors", "books");
}
/*
@@ -83,6 +85,20 @@ public class JpaWebTests extends AbstractWebIntegrationTests {
return Collections.singletonMap("people", readFile("person.json"));
}
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.rest.webmvc.AbstractWebIntegrationTests#getRootAndLinkedResources()
+ */
+ @Override
+ protected MultiValueMap getRootAndLinkedResources() {
+
+ MultiValueMap map = new LinkedMultiValueMap();
+ map.add("authors", "books");
+ map.add("books", "authors");
+
+ return map;
+ }
+
/**
* @see DATAREST-99
*/
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/TestDataPopulator.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/TestDataPopulator.java
index bea692ccb..c35fa2b23 100644
--- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/TestDataPopulator.java
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/jpa/TestDataPopulator.java
@@ -13,17 +13,43 @@ public class TestDataPopulator {
private final PersonRepository people;
private final OrderRepository orders;
+ private final AuthorRepository authorRepository;
+ private final BookRepository books;
@Autowired
- public TestDataPopulator(PersonRepository people, OrderRepository orders) {
+ public TestDataPopulator(PersonRepository people, OrderRepository orders, AuthorRepository authors,
+ BookRepository books) {
+
this.people = people;
this.orders = orders;
+ this.authorRepository = authors;
+ this.books = books;
}
public void populateRepositories() {
populatePeople();
populateOrders();
+ populateAuthorsAndBooks();
+ }
+
+ private void populateAuthorsAndBooks() {
+
+ if (authorRepository.count() != 0 || books.count() != 0) {
+ return;
+ }
+
+ Author ollie = new Author("Ollie");
+ Author mark = new Author("Mark");
+ Author michael = new Author("Michael");
+ Author david = new Author("David");
+ Author john = new Author("John");
+ Author thomas = new Author("Thomas");
+
+ Iterable authors = authorRepository.save(Arrays.asList(ollie, mark, michael, david, john, thomas));
+
+ books.save(new Book("1449323952", "Spring Data", authors));
+ books.save(new Book("1449323953", "Spring Data (SecondEdition)", authors));
}
private void populateOrders() {
@@ -56,4 +82,5 @@ public class TestDataPopulator {
people.save(Arrays.asList(john, jane));
}
+
}
diff --git a/spring-data-rest-webmvc/src/test/resources/logback.xml b/spring-data-rest-webmvc/src/test/resources/logback.xml
index a02b71a9a..7a648be10 100644
--- a/spring-data-rest-webmvc/src/test/resources/logback.xml
+++ b/spring-data-rest-webmvc/src/test/resources/logback.xml
@@ -7,7 +7,7 @@
-
+