diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java
index 863c30381..5c708654f 100644
--- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java
+++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/PersistentEntityJackson2Module.java
@@ -594,27 +594,53 @@ public class PersistentEntityJackson2Module extends SimpleModule {
PersistentEntity, ?> entity = entities.getPersistentEntity(object.getClass());
- Link selfLink = getSelfLink(object, entity, new Links(existingLinks));
+ Links links = new Links(existingLinks);
+ Link selfLink = createSelfLink(object, entity, links);
+
+ if (selfLink == null) {
+ return links;
+ }
+
Path path = new Path(selfLink.expand().getHref());
LinkCollectingAssociationHandler handler = new LinkCollectingAssociationHandler(entities, path, associationLinks);
entity.doWithAssociations(handler);
- List result = new ArrayList();
- result.add(getSelfLink(object, entity, new Links(existingLinks)));
+ List result = new ArrayList(existingLinks);
result.addAll(handler.getLinks());
- return new Links(result);
+ return addSelfLinkIfNecessary(object, entity, result);
}
- private Link getSelfLink(Object object, PersistentEntity, ?> entity, Links existing) {
+ private Links addSelfLinkIfNecessary(Object object, PersistentEntity, ?> entity, List existing) {
+
+ Links result = new Links(existing);
+
+ if (result.hasLink(Link.REL_SELF)) {
+ return result;
+ }
+
+ List list = new ArrayList();
+ list.add(createSelfLink(object, entity, result));
+ list.addAll(existing);
+
+ return new Links(list);
+ }
+
+ private Link createSelfLink(Object object, PersistentEntity, ?> entity, Links existing) {
if (existing.hasLink(Link.REL_SELF)) {
return existing.getLink(Link.REL_SELF);
}
IdentifierAccessor accessor = entity.getIdentifierAccessor(object);
- return links.linkToSingleResource(entity.getType(), accessor.getIdentifier()).withSelfRel();
+ Object identifier = accessor.getIdentifier();
+
+ if (identifier == null) {
+ return null;
+ }
+
+ return links.linkToSingleResource(entity.getType(), identifier).withSelfRel();
}
}
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntitySerializationTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntitySerializationTests.java
index da320a092..11fa91562 100644
--- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntitySerializationTests.java
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/PersistentEntitySerializationTests.java
@@ -48,13 +48,15 @@ import org.springframework.hateoas.PagedResources.PageMetadata;
import org.springframework.hateoas.core.EmbeddedWrapper;
import org.springframework.hateoas.core.EmbeddedWrappers;
import org.springframework.hateoas.hal.HalLinkDiscoverer;
+import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.util.UriTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
import com.jayway.jsonpath.JsonPath;
/**
@@ -82,6 +84,8 @@ public class PersistentEntitySerializationTests {
@Before
public void setUp() {
+ RequestContextHolder.setRequestAttributes(new ServletWebRequest(new MockHttpServletRequest()));
+
this.linkDiscoverer = new HalLinkDiscoverer();
this.projectionFactory = new SpelAwareProxyProjectionFactory();
}
@@ -234,9 +238,11 @@ public class PersistentEntitySerializationTests {
@Test
public void serializesLinksForExcerpts() throws Exception {
- Person oliver = new Person("Oliver August", "Matthews");
-
Person dave = new Person("Dave", "Matthews");
+ dave.setId(1L);
+
+ Person oliver = new Person("Oliver August", "Matthews");
+ oliver.setId(2L);
oliver.setFather(dave);
UserExcerpt daveExcerpt = projectionFactory.createProjection(UserExcerpt.class, dave);
@@ -248,9 +254,27 @@ public class PersistentEntitySerializationTests {
withEmbedded(Arrays.asList(wrapper)).//
build();
- mapper.enable(SerializationFeature.INDENT_OUTPUT);
String result = mapper.writeValueAsString(resource);
assertThat(JsonPath.read(result, "$_embedded.father[*]._links.self"), is(notNullValue()));
}
+
+ /**
+ * @see DATAREST-521
+ */
+ @Test
+ public void rendersAdditionalLinksRegisteredWithResource() throws Exception {
+
+ Person dave = new Person("Dave", "Matthews");
+
+ PersistentEntityResource resource = PersistentEntityResource.//
+ build(dave, repositories.getPersistentEntity(Person.class)).//
+ withLink(new Link("/people/1")).//
+ withLink(new Link("/aditional", "processed")).//
+ build();
+
+ String result = mapper.writeValueAsString(resource);
+
+ assertThat(JsonPath.read(result, "$_links.processed"), is(notNullValue()));
+ }
}
diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/RepositoryTestsConfig.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/RepositoryTestsConfig.java
index 7ed0f7a37..0cbe072e2 100644
--- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/RepositoryTestsConfig.java
+++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/json/RepositoryTestsConfig.java
@@ -15,13 +15,12 @@
*/
package org.springframework.data.rest.webmvc.json;
-import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import org.mockito.Matchers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@@ -38,13 +37,17 @@ import org.springframework.data.rest.webmvc.jpa.JpaRepositoryConfig;
import org.springframework.data.rest.webmvc.jpa.Person;
import org.springframework.data.rest.webmvc.jpa.PersonRepository;
import org.springframework.data.rest.webmvc.mongodb.MongoDbRepositoryConfig;
+import org.springframework.data.rest.webmvc.spi.BackendIdConverter;
+import org.springframework.data.rest.webmvc.spi.BackendIdConverter.DefaultIdConverter;
+import org.springframework.data.rest.webmvc.support.PagingAndSortingTemplateVariables;
+import org.springframework.data.rest.webmvc.support.RepositoryEntityLinks;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.hateoas.EntityLinks;
-import org.springframework.hateoas.Link;
import org.springframework.hateoas.RelProvider;
import org.springframework.hateoas.core.EvoInflectorRelProvider;
import org.springframework.hateoas.hal.Jackson2HalModule;
+import org.springframework.plugin.core.OrderAwarePluginRegistry;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
@@ -101,12 +104,13 @@ public class RepositoryTestsConfig {
@Bean
public Module persistentEntityModule() {
- EntityLinks entityLinks = mock(EntityLinks.class);
- when(entityLinks.linkToSingleResource(Matchers.> any(), anyObject())).thenReturn(new Link("/mock/1"));
+ RepositoryResourceMappings mappings = new RepositoryResourceMappings(repositories(), persistentEntities());
+ EntityLinks entityLinks = new RepositoryEntityLinks(repositories(), mappings, config(),
+ mock(PagingAndSortingTemplateVariables.class),
+ OrderAwarePluginRegistry., BackendIdConverter> create(Arrays.asList(DefaultIdConverter.INSTANCE)));
- return new PersistentEntityJackson2Module(new RepositoryResourceMappings(repositories(), persistentEntities()),
- persistentEntities(), config(), new UriToEntityConverter(persistentEntities(), defaultConversionService()),
- entityLinks);
+ return new PersistentEntityJackson2Module(mappings, persistentEntities(), config(), new UriToEntityConverter(
+ persistentEntities(), defaultConversionService()), entityLinks);
}
@Bean