16
16
package org .springframework .data .rest .webmvc .json ;
17
17
18
18
import static org .assertj .core .api .Assertions .*;
19
+ import static org .mockito .ArgumentMatchers .*;
19
20
import static org .mockito .Mockito .*;
20
21
22
+ import lombok .Getter ;
23
+
21
24
import java .io .IOException ;
22
25
import java .net .URI ;
23
26
import java .util .Arrays ;
24
27
import java .util .Collections ;
28
+ import java .util .Optional ;
25
29
26
30
import org .junit .Before ;
27
31
import org .junit .Test ;
32
36
import org .springframework .data .keyvalue .core .mapping .context .KeyValueMappingContext ;
33
37
import org .springframework .data .mapping .PersistentProperty ;
34
38
import org .springframework .data .mapping .context .PersistentEntities ;
39
+ import org .springframework .data .repository .support .RepositoryInvoker ;
35
40
import org .springframework .data .repository .support .RepositoryInvokerFactory ;
36
41
import org .springframework .data .rest .core .UriToEntityConverter ;
37
42
import org .springframework .data .rest .core .mapping .ResourceMappings ;
43
+ import org .springframework .data .rest .core .support .EntityLookup ;
38
44
import org .springframework .data .rest .core .support .SelfLinkProvider ;
39
45
import org .springframework .data .rest .core .util .Java8PluginRegistry ;
40
46
import org .springframework .data .rest .webmvc .EmbeddedResourcesAssembler ;
49
55
import org .springframework .hateoas .UriTemplate ;
50
56
import org .springframework .hateoas .mvc .ResourceProcessorInvoker ;
51
57
58
+ import com .fasterxml .jackson .annotation .JsonInclude ;
59
+ import com .fasterxml .jackson .annotation .JsonInclude .Include ;
52
60
import com .fasterxml .jackson .annotation .JsonProperty ;
53
61
import com .fasterxml .jackson .annotation .JsonTypeInfo ;
54
62
import com .fasterxml .jackson .databind .ObjectMapper ;
@@ -69,6 +77,7 @@ public class PersistentEntityJackson2ModuleUnitTests {
69
77
@ Mock EntityLinks entityLinks ;
70
78
@ Mock ResourceMappings mappings ;
71
79
@ Mock SelfLinkProvider selfLinks ;
80
+ @ Mock RepositoryInvokerFactory factory ;
72
81
73
82
PersistentEntities persistentEntities ;
74
83
ObjectMapper mapper ;
@@ -90,9 +99,9 @@ public void setUp() {
90
99
SimpleModule module = new SimpleModule ();
91
100
92
101
module .setSerializerModifier (new AssociationOmittingSerializerModifier (persistentEntities , associations ,
93
- nestedEntitySerializer , new LookupObjectSerializer (Java8PluginRegistry .empty ( ))));
94
- module .setDeserializerModifier (new AssociationUriResolvingDeserializerModifier ( persistentEntities , associations ,
95
- converter , mock ( RepositoryInvokerFactory . class ) ));
102
+ nestedEntitySerializer , new LookupObjectSerializer (Java8PluginRegistry .of ( Arrays . asList ( new HomeLookup ()) ))));
103
+ module .setDeserializerModifier (
104
+ new AssociationUriResolvingDeserializerModifier ( persistentEntities , associations , converter , factory ));
96
105
97
106
this .mapper = new ObjectMapper ();
98
107
this .mapper .registerModule (module );
@@ -135,20 +144,80 @@ public void resolvesReferenceToSubtypeCorrectly() throws IOException {
135
144
assertThat (petOwner .getPet ()).isNotNull ();
136
145
}
137
146
138
- static class PetOwner {
147
+ @ Test // DATAREST-1321
148
+ public void allowsNumericIdsForLookupTypes () throws Exception {
139
149
140
- Pet pet ;
150
+ RepositoryInvoker invoker = mock (RepositoryInvoker .class );
151
+ when (invoker .invokeFindById (any (Long .class ))).thenReturn (Optional .of (new Home ()));
152
+
153
+ when (factory .getInvokerFor (Home .class )).thenReturn (invoker );
154
+
155
+ PersistentProperty <?> property = persistentEntities .getRequiredPersistentEntity (PetOwner .class )
156
+ .getRequiredPersistentProperty ("home" );
157
+
158
+ when (associations .isLookupType (property )).thenReturn (true );
159
+
160
+ PetOwner petOwner = mapper .readValue ("{\" home\" : 1 }" , PetOwner .class );
161
+
162
+ assertThat (petOwner ).isNotNull ();
163
+ assertThat (petOwner .getHome ()).isInstanceOf (Home .class );
164
+ }
165
+
166
+ @ Test // DATAREST-1321
167
+ public void serializesNonStringLookupValues () throws Exception {
168
+
169
+ // Given Pet defined as lookup type
170
+ PersistentProperty <?> property = persistentEntities .getRequiredPersistentEntity (PetOwner .class )
171
+ .getRequiredPersistentProperty ("home" );
172
+ when (associations .isLookupType (property )).thenReturn (true );
173
+
174
+ // When a Pet is rendered
175
+ PetOwner owner = new PetOwner ();
176
+ owner .home = new Home ();
141
177
142
- public Pet getPet () {
143
- return pet ;
178
+ String result = mapper .writeValueAsString (owner );
179
+
180
+ // The it appears as numeric value
181
+ assertThat (JsonPath .parse (result ).read ("$.home" , Integer .class )) //
182
+ .isEqualTo (41 );
183
+ }
184
+
185
+ /**
186
+ * @author Oliver Gierke
187
+ */
188
+ private static class HomeLookup implements EntityLookup <Home > {
189
+
190
+ @ Override
191
+ public Object getResourceIdentifier (Home entity ) {
192
+ return 41 ;
193
+ }
194
+
195
+ @ Override
196
+ public boolean supports (Class <?> delimiter ) {
197
+ return delimiter .equals (Home .class );
198
+ }
199
+
200
+ @ Override
201
+ public Optional <Home > lookupEntity (Object id ) {
202
+ return Optional .of (new Home ());
144
203
}
145
204
}
146
205
206
+ @ Getter
207
+ @ JsonInclude (Include .NON_NULL )
208
+ static class PetOwner {
209
+
210
+ Pet pet ;
211
+ Home home ;
212
+ }
213
+
147
214
@ JsonTypeInfo (include = JsonTypeInfo .As .PROPERTY , use = JsonTypeInfo .Id .MINIMAL_CLASS )
148
215
static class Pet {}
149
216
150
217
static class Cat extends Pet {}
151
218
219
+ static class Home {}
220
+
152
221
static class Sample {
153
222
public @ JsonProperty ("foo" ) String name ;
154
223
}
0 commit comments