diff --git a/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java b/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java index f3f95d8e..c7ae0946 100644 --- a/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java +++ b/rest-notes-spring-data-rest/src/test/java/com/example/notes/ApiDocumentation.java @@ -19,7 +19,6 @@ package com.example.notes; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.springframework.restdocs.core.RestDocumentation.document; -import static org.springframework.restdocs.core.LinkExtractors.halLinks; import static org.springframework.restdocs.core.RestDocumentation.linkWithRel; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; @@ -95,7 +94,7 @@ public class ApiDocumentation { public void indexExample() throws Exception { this.mockMvc.perform(get("/")) .andExpect(status().isOk()) - .andDo(document("index-example").withLinks(halLinks(), + .andDo(document("index-example").withLinks( linkWithRel("notes").description( "The <>"), linkWithRel("tags").description( @@ -175,7 +174,7 @@ public class ApiDocumentation { .andExpect(jsonPath("_links.self.href", is(noteLocation))) .andExpect(jsonPath("_links.tags", is(notNullValue()))) .andDo(document("note-get-example") - .withLinks(halLinks(), + .withLinks( linkWithRel("self").description("This <>"), linkWithRel("tags").description( "This note's <>"))); @@ -262,7 +261,7 @@ public class ApiDocumentation { this.mockMvc.perform(get(tagLocation)) .andExpect(status().isOk()) .andExpect(jsonPath("name", is(tag.get("name")))) - .andDo(document("tag-get-example").withLinks(halLinks(), + .andDo(document("tag-get-example").withLinks( linkWithRel("self").description("This <>"), linkWithRel("notes") .description( diff --git a/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java b/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java index da8ca724..7e201ed2 100644 --- a/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java +++ b/rest-notes-spring-hateoas/src/test/java/com/example/notes/ApiDocumentation.java @@ -18,7 +18,6 @@ package com.example.notes; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.springframework.restdocs.core.LinkExtractors.halLinks; import static org.springframework.restdocs.core.RestDocumentation.document; import static org.springframework.restdocs.core.RestDocumentation.linkWithRel; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -95,7 +94,7 @@ public class ApiDocumentation { public void indexExample() throws Exception { this.mockMvc.perform(get("/")) .andExpect(status().isOk()) - .andDo(document("index-example").withLinks(halLinks(), + .andDo(document("index-example").withLinks( linkWithRel("notes").description( "The <>"), linkWithRel("tags").description( @@ -171,7 +170,7 @@ public class ApiDocumentation { .andExpect(jsonPath("body", is(note.get("body")))) .andExpect(jsonPath("_links.self.href", is(noteLocation))) .andExpect(jsonPath("_links.note-tags", is(notNullValue()))) - .andDo(document("note-get-example").withLinks(halLinks(), + .andDo(document("note-get-example").withLinks( linkWithRel("self").description("This <>"), linkWithRel("note-tags").description( "This note's <>"))); @@ -258,7 +257,7 @@ public class ApiDocumentation { this.mockMvc.perform(get(tagLocation)) .andExpect(status().isOk()) .andExpect(jsonPath("name", is(tag.get("name")))) - .andDo(document("tag-get-example").withLinks(halLinks(), + .andDo(document("tag-get-example").withLinks( linkWithRel("self").description("This <>"), linkWithRel("tagged-notes") .description( diff --git a/spring-restdocs-core/.settings/org.eclipse.jdt.ui.prefs b/spring-restdocs-core/.settings/org.eclipse.jdt.ui.prefs index ca171a90..dc84ae74 100644 --- a/spring-restdocs-core/.settings/org.eclipse.jdt.ui.prefs +++ b/spring-restdocs-core/.settings/org.eclipse.jdt.ui.prefs @@ -120,6 +120,6 @@ sp_cleanup.use_lambda=true sp_cleanup.use_parentheses_in_expressions=false sp_cleanup.use_this_for_non_static_field_access=true sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false -sp_cleanup.use_this_for_non_static_method_access=true +sp_cleanup.use_this_for_non_static_method_access=false sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false sp_cleanup.use_type_arguments=false diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkExtractors.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkExtractors.java index f736e07d..df35102e 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkExtractors.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/LinkExtractors.java @@ -24,16 +24,16 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletResponse; import com.fasterxml.jackson.databind.ObjectMapper; /** - * Static factory methods provided a selection of {@link LinkExtractor link extractors} + * Static factory methods providing a selection of {@link LinkExtractor link extractors} * for use when documentating a hypermedia-based API. * * @author Andy Wilkinson - * */ public class LinkExtractors { @@ -58,6 +58,23 @@ public class LinkExtractors { return new AtomLinkExtractor(); } + /** + * Returns the {@code LinkExtractor} for the given {@code contentType} or {@code null} + * if there is no extractor for the content type. + * + * @param contentType The content type + * @return The extractor for the content type, or {@code null} + */ + public static LinkExtractor extractorForContentType(String contentType) { + if (MediaType.APPLICATION_JSON_VALUE.equals(contentType)) { + return atomLinks(); + } + else if ("application/hal+json".equals(contentType)) { + return halLinks(); + } + return null; + } + private static abstract class JsonContentLinkExtractor implements LinkExtractor { private final ObjectMapper objectMapper = new ObjectMapper(); diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandler.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandler.java index 71eca294..a5464bfd 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandler.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandler.java @@ -47,6 +47,10 @@ public class RestDocumentationResultHandler implements ResultHandler { } } + public RestDocumentationResultHandler withLinks(LinkDescriptor... descriptors) { + return withLinks(null, descriptors); + } + public RestDocumentationResultHandler withLinks(LinkExtractor linkExtractor, LinkDescriptor... descriptors) { this.linkDocumentingResultHandler = new LinkDocumentingResultHandler( diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandlers.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandlers.java index 256279d0..7b066cc2 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandlers.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/core/RestDocumentationResultHandlers.java @@ -260,8 +260,24 @@ public abstract class RestDocumentationResultHandlers { @Override void handle(MvcResult result, DocumentationWriter writer) throws Exception { - Map> links = this.extractor.extractLinks(result - .getResponse()); + Map> links; + if (this.extractor != null) { + links = this.extractor.extractLinks(result.getResponse()); + } + else { + String contentType = result.getResponse().getContentType(); + LinkExtractor extractorForContentType = LinkExtractors + .extractorForContentType(contentType); + if (extractorForContentType != null) { + links = extractorForContentType.extractLinks(result.getResponse()); + } + else { + throw new IllegalStateException( + "No LinkExtractor has been provided and one is not available for the content type " + + contentType); + } + + } Set actualRels = links.keySet(); Set expectedRels = this.descriptorsByRel.keySet();