Skip to content

Commit 2ae4f0c

Browse files
committed
DATAREST-1205 - Use Affordances API
Leverage the Affordances API while making other media types work.
1 parent c316334 commit 2ae4f0c

File tree

23 files changed

+787
-54
lines changed

23 files changed

+787
-54
lines changed

spring-data-rest-core/pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
</parent>
1717

1818
<properties>
19-
<springplugin>1.2.0.RELEASE</springplugin>
19+
<springplugin>2.0.0.BUILD-SNAPSHOT</springplugin>
2020
<evoinflector>1.2.2</evoinflector>
21+
<spring-hateoas>1.0.0.SDR-SNAPSHOT</spring-hateoas>
2122
<java-module-name>spring.data.rest.core</java-module-name>
2223
</properties>
2324

spring-data-rest-core/src/main/java/org/springframework/data/rest/core/util/Java8PluginRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public static <T extends Plugin<S>, S> Java8PluginRegistry<T, S> empty() {
4646
}
4747

4848
public Optional<T> getPluginFor(S delimiter) {
49-
return Optional.ofNullable(registry.getPluginFor(delimiter));
49+
return registry.getPluginFor(delimiter);
5050
}
5151

5252
public T getPluginOrDefaultFor(S delimiter, T fallback) {

spring-data-rest-tests/spring-data-rest-tests-core/src/test/java/org/springframework/data/rest/tests/ResourceTester.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public Link assertHasLinkEndingWith(String rel, String hrefEnd) {
8383

8484
private final Link assertHasLinkMatching(String rel, Matcher<String> hrefMatcher) {
8585

86-
Link link = resource.getLink(rel);
86+
Link link = resource.getRequiredLink(rel);
8787
assertThat("Expected link with rel '" + rel + "' but didn't find it in " + resource.getLinks(), link,
8888
is(notNullValue()));
8989

spring-data-rest-tests/spring-data-rest-tests-jpa/pom.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,19 @@
4747
<scope>test</scope>
4848
</dependency>
4949

50+
<dependency>
51+
<groupId>org.springframework</groupId>
52+
<artifactId>spring-web</artifactId>
53+
<version>${spring}</version>
54+
</dependency>
55+
56+
<dependency>
57+
<groupId>org.springframework.hateoas</groupId>
58+
<artifactId>spring-hateoas</artifactId>
59+
<version>1.0.0.SDR-SNAPSHOT</version>
60+
<scope>test</scope>
61+
</dependency>
62+
5063
<!-- Jackson Hibernate -->
5164

5265
<dependency>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
/*
2+
* Copyright 2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.rest.webmvc;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.hamcrest.collection.IsCollectionWithSize.*;
20+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
21+
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
22+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
23+
24+
import org.junit.Test;
25+
import org.springframework.beans.factory.annotation.Autowired;
26+
import org.springframework.data.rest.tests.AbstractWebIntegrationTests;
27+
import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
28+
import org.springframework.data.rest.webmvc.jpa.TestDataPopulator;
29+
import org.springframework.hateoas.Link;
30+
import org.springframework.hateoas.MediaTypes;
31+
import org.springframework.hateoas.hal.HalLinkDiscoverer;
32+
import org.springframework.hateoas.hal.forms.HalFormsLinkDiscoverer;
33+
import org.springframework.http.HttpHeaders;
34+
import org.springframework.test.context.ContextConfiguration;
35+
import org.springframework.transaction.annotation.Transactional;
36+
37+
/**
38+
* @author Greg Turnquist
39+
*/
40+
@Transactional
41+
@ContextConfiguration(classes = JpaRepositoryConfig.class)
42+
public class AffordanceIntegrationTests extends AbstractWebIntegrationTests {
43+
44+
HalLinkDiscoverer halLinkDiscoverer;
45+
46+
HalFormsLinkDiscoverer halFormsLinkDiscoverer;
47+
48+
@Autowired TestDataPopulator loader;
49+
50+
@Override
51+
public void setUp() {
52+
53+
loader.populateRepositories();
54+
halLinkDiscoverer = new HalLinkDiscoverer();
55+
halFormsLinkDiscoverer = new HalFormsLinkDiscoverer();
56+
57+
super.setUp();
58+
}
59+
60+
@Test
61+
public void tests() throws Exception {
62+
63+
mvc.perform(get("/")
64+
.header(HttpHeaders.ACCEPT, MediaTypes.HAL_JSON))
65+
.andDo(print())
66+
.andExpect(status().isOk());
67+
68+
mvc.perform(get("/")
69+
.header(HttpHeaders.ACCEPT, MediaTypes.HAL_FORMS_JSON))
70+
.andDo(print())
71+
.andExpect(status().isOk());
72+
73+
mvc.perform(get("/")
74+
.header(HttpHeaders.ACCEPT, MediaTypes.COLLECTION_JSON))
75+
.andDo(print())
76+
.andExpect(status().isOk());
77+
78+
String halFormsSingleItemResults = mvc.perform(get("/people/1")
79+
.header(HttpHeaders.ACCEPT, MediaTypes.HAL_FORMS_JSON))
80+
.andDo(print())
81+
.andExpect(status().isOk())
82+
.andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaTypes.HAL_FORMS_JSON_VALUE + ";charset=UTF-8"))
83+
.andExpect(jsonPath("$.firstName").value("Billy Bob"))
84+
.andExpect(jsonPath("$.lastName").value("Thornton"))
85+
.andExpect(jsonPath("$._links[*]", hasSize(4)))
86+
.andReturn().getResponse().getContentAsString()
87+
;
88+
89+
assertThat(halFormsLinkDiscoverer.findLinkWithRel(Link.REL_SELF, halFormsSingleItemResults)).isEqualTo(new Link("http://localhost/people/1"));
90+
assertThat(halFormsLinkDiscoverer.findLinkWithRel("person", halFormsSingleItemResults)).isEqualTo(new Link("http://localhost/people/1{?projection}", "person"));
91+
assertThat(halFormsLinkDiscoverer.findLinkWithRel("siblings", halFormsSingleItemResults)).isEqualTo(new Link("http://localhost/people/1/siblings{?projection}", "siblings"));
92+
assertThat(halFormsLinkDiscoverer.findLinkWithRel("father", halFormsSingleItemResults)).isEqualTo(new Link("http://localhost/people/1/father{?projection}", "father"));
93+
94+
String halFormsSingleItemResults2 = mvc.perform(get("/people/2")
95+
.header(HttpHeaders.ACCEPT, MediaTypes.HAL_FORMS_JSON))
96+
.andDo(print())
97+
.andExpect(status().isOk())
98+
.andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaTypes.HAL_FORMS_JSON_VALUE + ";charset=UTF-8"))
99+
.andExpect(jsonPath("$.firstName").value("John"))
100+
.andExpect(jsonPath("$.lastName").value("Doe"))
101+
.andExpect(jsonPath("$._links[*]", hasSize(4)))
102+
.andReturn().getResponse().getContentAsString()
103+
;
104+
105+
String halSingleItemResults = mvc.perform(get("/people/1")
106+
.header(HttpHeaders.ACCEPT, MediaTypes.HAL_JSON))
107+
.andDo(print())
108+
.andExpect(status().isOk())
109+
.andExpect(jsonPath("$._links[*]", hasSize(4)))
110+
.andReturn().getResponse().getContentAsString();
111+
112+
assertThat(halLinkDiscoverer.findLinkWithRel(Link.REL_SELF, halSingleItemResults)).isEqualTo(new Link("http://localhost/people/1"));
113+
assertThat(halLinkDiscoverer.findLinkWithRel("person", halSingleItemResults)).isEqualTo(new Link("http://localhost/people/1{?projection}", "person"));
114+
assertThat(halLinkDiscoverer.findLinkWithRel("siblings", halSingleItemResults)).isEqualTo(new Link("http://localhost/people/1/siblings{?projection}", "siblings"));
115+
assertThat(halLinkDiscoverer.findLinkWithRel("father", halSingleItemResults)).isEqualTo(new Link("http://localhost/people/1/father{?projection}", "father"));
116+
117+
String collectionJsonSingleItemResults = mvc.perform(get("/people/1")
118+
.header(HttpHeaders.ACCEPT, MediaTypes.COLLECTION_JSON))
119+
.andDo(print())
120+
.andExpect(status().isOk())
121+
.andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaTypes.COLLECTION_JSON_VALUE + ";charset=UTF-8"))
122+
.andExpect(jsonPath("$.collection.href").value("http://localhost/people/1"))
123+
.andExpect(jsonPath("$.collection.links[*]", hasSize(3)))
124+
.andExpect(jsonPath("$.collection.items[0].href").value("http://localhost/people/1"))
125+
.andExpect(jsonPath("$.collection.items[0].data[0].name").value("firstName"))
126+
.andExpect(jsonPath("$.collection.items[0].data[0].value").value("Billy Bob"))
127+
.andExpect(jsonPath("$.collection.items[0].data[1].name").value("lastName"))
128+
.andExpect(jsonPath("$.collection.items[0].data[1].value").value("Thornton"))
129+
.andExpect(jsonPath("$.collection.items[0].links[*]", hasSize(3)))
130+
.andExpect(jsonPath("$.collection.template.data[0].name").value("age"))
131+
.andExpect(jsonPath("$.collection.template.data[1].name").value("created"))
132+
.andExpect(jsonPath("$.collection.template.data[2].name").value("father"))
133+
.andExpect(jsonPath("$.collection.template.data[3].name").value("firstName"))
134+
.andExpect(jsonPath("$.collection.template.data[4].name").value("gender"))
135+
.andExpect(jsonPath("$.collection.template.data[5].name").value("height"))
136+
.andExpect(jsonPath("$.collection.template.data[6].name").value("id"))
137+
.andExpect(jsonPath("$.collection.template.data[7].name").value("lastName"))
138+
.andExpect(jsonPath("$.collection.template.data[8].name").value("siblings"))
139+
.andExpect(jsonPath("$.collection.template.data[9].name").value("weight"))
140+
.andReturn().getResponse().getContentAsString()
141+
;
142+
143+
String collectionJsonSingleItemResults2 = mvc.perform(get("/people/2")
144+
.header(HttpHeaders.ACCEPT, MediaTypes.COLLECTION_JSON))
145+
.andDo(print())
146+
.andExpect(status().isOk())
147+
.andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaTypes.COLLECTION_JSON_VALUE + ";charset=UTF-8"))
148+
.andExpect(jsonPath("$.collection.href").value("http://localhost/people/2"))
149+
.andExpect(jsonPath("$.collection.links[*]", hasSize(3)))
150+
.andExpect(jsonPath("$.collection.items[0].href").value("http://localhost/people/2"))
151+
.andExpect(jsonPath("$.collection.items[0].data[0].name").value("firstName"))
152+
.andExpect(jsonPath("$.collection.items[0].data[0].value").value("John"))
153+
.andExpect(jsonPath("$.collection.items[0].data[1].name").value("lastName"))
154+
.andExpect(jsonPath("$.collection.items[0].data[1].value").value("Doe"))
155+
.andExpect(jsonPath("$.collection.items[0].links[*]", hasSize(3)))
156+
.andExpect(jsonPath("$.collection.template.data[0].name").value("age"))
157+
.andExpect(jsonPath("$.collection.template.data[1].name").value("created"))
158+
.andExpect(jsonPath("$.collection.template.data[2].name").value("father"))
159+
.andExpect(jsonPath("$.collection.template.data[3].name").value("firstName"))
160+
.andExpect(jsonPath("$.collection.template.data[4].name").value("gender"))
161+
.andExpect(jsonPath("$.collection.template.data[5].name").value("height"))
162+
.andExpect(jsonPath("$.collection.template.data[6].name").value("id"))
163+
.andExpect(jsonPath("$.collection.template.data[7].name").value("lastName"))
164+
.andExpect(jsonPath("$.collection.template.data[8].name").value("siblings"))
165+
.andExpect(jsonPath("$.collection.template.data[9].name").value("weight"))
166+
.andReturn().getResponse().getContentAsString()
167+
;
168+
169+
String halFormsAggregateResults = mvc.perform(get("/people")
170+
.header(HttpHeaders.ACCEPT, MediaTypes.HAL_FORMS_JSON))
171+
.andDo(print())
172+
.andExpect(status().isOk())
173+
.andExpect(jsonPath("$._links[*]", hasSize(3)))
174+
.andExpect(jsonPath("$.page.size").value(20))
175+
.andExpect(jsonPath("$.page.totalElements").value(3))
176+
.andExpect(jsonPath("$.page.totalPages").value(1))
177+
.andExpect(jsonPath("$.page.number").value(0))
178+
.andReturn().getResponse().getContentAsString();
179+
180+
assertThat(halFormsLinkDiscoverer.findLinkWithRel(Link.REL_SELF, halFormsAggregateResults)).isEqualTo(new Link("http://localhost/people{?page,size,sort,projection}"));
181+
assertThat(halFormsLinkDiscoverer.findLinkWithRel("profile", halFormsAggregateResults)).isEqualTo(new Link("http://localhost/profile/people", "profile"));
182+
assertThat(halFormsLinkDiscoverer.findLinkWithRel("search", halFormsAggregateResults)).isEqualTo(new Link("http://localhost/people/search", "search"));
183+
184+
String halFormsPageRequest = mvc.perform(get("/people")
185+
.param("page", "1")
186+
.param("size", "1")
187+
.header(HttpHeaders.ACCEPT, MediaTypes.HAL_FORMS_JSON))
188+
.andDo(print())
189+
.andExpect(status().isOk())
190+
.andExpect(jsonPath("$._embedded.people[0].firstName").value("John"))
191+
.andExpect(jsonPath("$._embedded.people[0].lastName").value("Doe"))
192+
.andExpect(jsonPath("$._embedded.people[0]._links[*]", hasSize(4)))
193+
.andExpect(jsonPath("$._links[*]", hasSize(7)))
194+
.andExpect(jsonPath("$.page.size").value(1))
195+
.andExpect(jsonPath("$.page.totalElements").value(3))
196+
.andExpect(jsonPath("$.page.totalPages").value(3))
197+
.andExpect(jsonPath("$.page.number").value(1))
198+
.andReturn().getResponse().getContentAsString();
199+
200+
assertThat(halFormsLinkDiscoverer.findLinkWithRel(Link.REL_SELF, halFormsPageRequest)).isEqualTo(new Link("http://localhost/people{&sort,projection}"));
201+
assertThat(halFormsLinkDiscoverer.findLinkWithRel(Link.REL_FIRST, halFormsPageRequest)).isEqualTo(new Link("http://localhost/people?page=0&size=1", Link.REL_FIRST));
202+
assertThat(halFormsLinkDiscoverer.findLinkWithRel(Link.REL_PREVIOUS, halFormsPageRequest)).isEqualTo(new Link("http://localhost/people?page=0&size=1", Link.REL_PREVIOUS));
203+
assertThat(halFormsLinkDiscoverer.findLinkWithRel(Link.REL_NEXT, halFormsPageRequest)).isEqualTo(new Link("http://localhost/people?page=2&size=1", Link.REL_NEXT));
204+
assertThat(halFormsLinkDiscoverer.findLinkWithRel(Link.REL_LAST, halFormsPageRequest)).isEqualTo(new Link("http://localhost/people?page=2&size=1", Link.REL_LAST));
205+
assertThat(halFormsLinkDiscoverer.findLinkWithRel("profile", halFormsPageRequest)).isEqualTo(new Link("http://localhost/profile/people", "profile"));
206+
assertThat(halFormsLinkDiscoverer.findLinkWithRel("search", halFormsPageRequest)).isEqualTo(new Link("http://localhost/people/search", "search"));
207+
208+
String collectionJsonAggregateResults = mvc.perform(get("/people")
209+
.header(HttpHeaders.ACCEPT, MediaTypes.COLLECTION_JSON))
210+
.andDo(print())
211+
.andExpect(status().isOk())
212+
.andExpect(jsonPath("$.collection.href").value("http://localhost/people{?page,size,sort,projection}"))
213+
.andExpect(jsonPath("$.collection.links[*]", hasSize(2)))
214+
.andExpect(jsonPath("$.collection.items[0].href").value("http://localhost/people/1"))
215+
.andExpect(jsonPath("$.collection.items[0].data[0].name").value("firstName"))
216+
.andExpect(jsonPath("$.collection.items[0].data[0].value").value("Billy Bob"))
217+
.andExpect(jsonPath("$.collection.items[0].data[1].name").value("lastName"))
218+
.andExpect(jsonPath("$.collection.items[0].data[1].value").value("Thornton"))
219+
.andExpect(jsonPath("$.collection.items[0].links[*]", hasSize(1)))
220+
.andExpect(jsonPath("$.collection.template.data[0].name").value("age"))
221+
.andExpect(jsonPath("$.collection.template.data[1].name").value("created"))
222+
.andExpect(jsonPath("$.collection.template.data[2].name").value("father"))
223+
.andExpect(jsonPath("$.collection.template.data[3].name").value("firstName"))
224+
.andExpect(jsonPath("$.collection.template.data[4].name").value("gender"))
225+
.andExpect(jsonPath("$.collection.template.data[5].name").value("height"))
226+
.andExpect(jsonPath("$.collection.template.data[6].name").value("id"))
227+
.andExpect(jsonPath("$.collection.template.data[7].name").value("lastName"))
228+
.andExpect(jsonPath("$.collection.template.data[8].name").value("siblings"))
229+
.andExpect(jsonPath("$.collection.template.data[9].name").value("weight"))
230+
.andReturn().getResponse().getContentAsString();
231+
232+
String collectionJsonPageRequest = mvc.perform(get("/people")
233+
.param("page", "1")
234+
.param("size", "1")
235+
.header(HttpHeaders.ACCEPT, MediaTypes.COLLECTION_JSON))
236+
.andDo(print())
237+
.andExpect(status().isOk())
238+
// .andExpect(jsonPath("$._embedded.people[0].firstName").value("John"))
239+
// .andExpect(jsonPath("$._embedded.people[0].lastName").value("Doe"))
240+
// .andExpect(jsonPath("$._embedded.people[0]._links[*]", hasSize(4)))
241+
// .andExpect(jsonPath("$._links[*]", hasSize(7)))
242+
// .andExpect(jsonPath("$.page.size").value(1))
243+
// .andExpect(jsonPath("$.page.totalElements").value(3))
244+
// .andExpect(jsonPath("$.page.totalPages").value(3))
245+
// .andExpect(jsonPath("$.page.number").value(1))
246+
.andReturn().getResponse().getContentAsString();
247+
}
248+
}

spring-data-rest-tests/spring-data-rest-tests-jpa/src/test/java/org/springframework/data/rest/webmvc/support/RepositoryEntityLinksIntegrationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public void returnsLinksToSearchResources() {
9999

100100
assertThat(links.hasLink("firstname")).isTrue();
101101

102-
Link firstnameLink = links.getLink("firstname");
102+
Link firstnameLink = links.getLink("firstname").orElse(null);
103103
assertThat(firstnameLink.isTemplated()).isTrue();
104104
assertThat(firstnameLink.getVariableNames()).contains("page", "size");
105105
}

spring-data-rest-tests/spring-data-rest-tests-mongodb/src/test/java/org/springframework/data/rest/webmvc/PersistentEntityResourceAssemblerIntegrationTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public void addsSelfAndSingleResourceLinkToResourceByDefault() throws Exception
7272
Links links = new Links(resource.getLinks());
7373

7474
assertThat(links).hasSize(2);
75-
assertThat(links.getLink("self").getVariables()).isEmpty();
76-
assertThat(links.getLink("user").getVariableNames()).contains("projection");
75+
assertThat(links.getLink("self").orElseThrow(() -> new RuntimeException("Unable to find 'self' link")).getVariables()).isEmpty();
76+
assertThat(links.getLink("user").orElseThrow(() -> new RuntimeException("Unable to find 'user' link")).getVariableNames()).contains("projection");
7777
}
7878
}

spring-data-rest-webmvc/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@
128128
<scope>test</scope>
129129
</dependency>
130130

131+
<dependency>
132+
<groupId>org.springframework.data</groupId>
133+
<artifactId>spring-data-jpa</artifactId>
134+
<version>${springdata.jpa}</version>
135+
<scope>test</scope>
136+
</dependency>
137+
131138
</dependencies>
132139

133140
</project>

spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/AbstractRepositoryRestController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ protected Link resourceLink(RootResourceInformation resourceLink, Resource resou
6363

6464
ResourceMetadata repoMapping = resourceLink.getResourceMetadata();
6565

66-
Link selfLink = resource.getLink("self");
66+
Link selfLink = resource.getRequiredLink(Link.REL_SELF);
6767
String rel = repoMapping.getItemResourceRel();
6868

6969
return new Link(selfLink.getHref(), rel);

spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResourceAssembler.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,13 @@
1515
*/
1616
package org.springframework.data.rest.webmvc;
1717

18+
import static org.springframework.hateoas.core.DummyInvocationUtils.*;
19+
1820
import lombok.NonNull;
1921
import lombok.RequiredArgsConstructor;
22+
import lombok.Value;
23+
24+
import java.lang.reflect.Method;
2025

2126
import org.springframework.data.mapping.PersistentEntity;
2227
import org.springframework.data.mapping.context.PersistentEntities;
@@ -28,7 +33,10 @@
2833
import org.springframework.hateoas.ResourceAssembler;
2934
import org.springframework.hateoas.core.EmbeddedWrapper;
3035
import org.springframework.hateoas.core.EmbeddedWrappers;
36+
import org.springframework.http.HttpMethod;
3137
import org.springframework.util.Assert;
38+
import org.springframework.web.util.UriComponents;
39+
import org.springframework.web.util.UriComponentsBuilder;
3240

3341
/**
3442
* {@link ResourceAssembler} to create {@link PersistentEntityResource}s for arbitrary domain objects.
@@ -71,10 +79,22 @@ private Builder wrap(Object instance, Object source) {
7179

7280
PersistentEntity<?, ?> entity = entities.getRequiredPersistentEntity(source.getClass());
7381

82+
Link selfLink = getSelfLinkFor(source);
83+
84+
SpringDataRestAffordance putItemAffordance = new SpringDataRestAffordance(HttpMethod.PUT, "put" + source.getClass().getSimpleName());
85+
putItemAffordance.addAffordanceModel(new SpringDataRestHalFormsAffordanceModel(putItemAffordance, instance, selfLink));
86+
putItemAffordance.addAffordanceModel(new SpringDataRestCollectionJsonAffordanceModel(putItemAffordance, instance, selfLink));
87+
88+
SpringDataRestAffordance patchItemAffordance = new SpringDataRestAffordance(HttpMethod.PATCH, "patch" + source.getClass().getSimpleName());
89+
patchItemAffordance.addAffordanceModel(new SpringDataRestHalFormsAffordanceModel(patchItemAffordance, instance, selfLink));
90+
patchItemAffordance.addAffordanceModel(new SpringDataRestCollectionJsonAffordanceModel(patchItemAffordance, instance, selfLink));
91+
7492
return PersistentEntityResource.build(instance, entity).//
75-
withEmbedded(getEmbeddedResources(source)).//
76-
withLink(getSelfLinkFor(source)).//
77-
withLink(linkProvider.createSelfLinkFor(source));
93+
withEmbedded(getEmbeddedResources(source)).//
94+
withLink(selfLink
95+
.andAffordance(putItemAffordance)
96+
.andAffordance(patchItemAffordance)).//
97+
withLink(linkProvider.createSelfLinkFor(source));
7898
}
7999

80100
/**

0 commit comments

Comments
 (0)