1616package org .springframework .data .rest .webmvc .json ;
1717
1818import static org .assertj .core .api .Assertions .*;
19+ import static org .mockito .ArgumentMatchers .*;
1920import static org .mockito .Mockito .*;
2021
22+ import lombok .Getter ;
23+
2124import java .io .IOException ;
2225import java .net .URI ;
2326import java .util .Arrays ;
2427import java .util .Collections ;
28+ import java .util .Optional ;
2529
2630import org .junit .Before ;
2731import org .junit .Test ;
3236import org .springframework .data .keyvalue .core .mapping .context .KeyValueMappingContext ;
3337import org .springframework .data .mapping .PersistentProperty ;
3438import org .springframework .data .mapping .context .PersistentEntities ;
39+ import org .springframework .data .repository .support .RepositoryInvoker ;
3540import org .springframework .data .repository .support .RepositoryInvokerFactory ;
3641import org .springframework .data .rest .core .UriToEntityConverter ;
3742import org .springframework .data .rest .core .mapping .ResourceMappings ;
43+ import org .springframework .data .rest .core .support .EntityLookup ;
3844import org .springframework .data .rest .core .support .SelfLinkProvider ;
3945import org .springframework .data .rest .core .util .Java8PluginRegistry ;
4046import org .springframework .data .rest .webmvc .EmbeddedResourcesAssembler ;
4955import org .springframework .hateoas .UriTemplate ;
5056import org .springframework .hateoas .mvc .ResourceProcessorInvoker ;
5157
58+ import com .fasterxml .jackson .annotation .JsonInclude ;
59+ import com .fasterxml .jackson .annotation .JsonInclude .Include ;
5260import com .fasterxml .jackson .annotation .JsonProperty ;
5361import com .fasterxml .jackson .annotation .JsonTypeInfo ;
5462import com .fasterxml .jackson .databind .ObjectMapper ;
@@ -69,6 +77,7 @@ public class PersistentEntityJackson2ModuleUnitTests {
6977 @ Mock EntityLinks entityLinks ;
7078 @ Mock ResourceMappings mappings ;
7179 @ Mock SelfLinkProvider selfLinks ;
80+ @ Mock RepositoryInvokerFactory factory ;
7281
7382 PersistentEntities persistentEntities ;
7483 ObjectMapper mapper ;
@@ -90,9 +99,9 @@ public void setUp() {
9099 SimpleModule module = new SimpleModule ();
91100
92101 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 ));
96105
97106 this .mapper = new ObjectMapper ();
98107 this .mapper .registerModule (module );
@@ -135,20 +144,80 @@ public void resolvesReferenceToSubtypeCorrectly() throws IOException {
135144 assertThat (petOwner .getPet ()).isNotNull ();
136145 }
137146
138- static class PetOwner {
147+ @ Test // DATAREST-1321
148+ public void allowsNumericIdsForLookupTypes () throws Exception {
139149
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 ();
141177
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 ());
144203 }
145204 }
146205
206+ @ Getter
207+ @ JsonInclude (Include .NON_NULL )
208+ static class PetOwner {
209+
210+ Pet pet ;
211+ Home home ;
212+ }
213+
147214 @ JsonTypeInfo (include = JsonTypeInfo .As .PROPERTY , use = JsonTypeInfo .Id .MINIMAL_CLASS )
148215 static class Pet {}
149216
150217 static class Cat extends Pet {}
151218
219+ static class Home {}
220+
152221 static class Sample {
153222 public @ JsonProperty ("foo" ) String name ;
154223 }
0 commit comments