DATAREST-925 - Invoke ResourceProcessors for ProjectionResources.

The serializer for projection resources now also invokes ResourceProcessor instances registered for that particular projection.

Original pull request: #238.
This commit is contained in:
Craig Andrews
2016-11-03 13:16:34 -04:00
committed by Oliver Gierke
parent 080d1b0dab
commit b66c8272ee
9 changed files with 94 additions and 25 deletions

View File

@@ -42,7 +42,6 @@ import org.springframework.data.rest.core.support.SelfLinkProvider;
import org.springframework.data.rest.webmvc.EmbeddedResourcesAssembler;
import org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module;
import org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module.LookupObjectSerializer;
import org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module.NestedEntitySerializer;
import org.springframework.data.rest.webmvc.mapping.Associations;
import org.springframework.data.rest.webmvc.mapping.LinkCollector;
import org.springframework.data.rest.webmvc.spi.BackendIdConverter;
@@ -123,12 +122,10 @@ public class RepositoryTestsConfig {
Associations associations = new Associations(mappings, config());
LinkCollector collector = new LinkCollector(persistentEntities(), selfLinkProvider, associations);
NestedEntitySerializer nestedEntitySerializer = new NestedEntitySerializer(persistentEntities(),
new EmbeddedResourcesAssembler(persistentEntities(), associations, mock(ExcerptProjector.class)),
new ResourceProcessorInvoker(Collections.<ResourceProcessor<?>> emptyList()));
return new PersistentEntityJackson2Module(associations, persistentEntities(), uriToEntityConverter, collector,
invokerFactory, nestedEntitySerializer, mock(LookupObjectSerializer.class));
invokerFactory, mock(LookupObjectSerializer.class),
new ResourceProcessorInvoker(Collections.<ResourceProcessor<?>> emptyList()),
new EmbeddedResourcesAssembler(persistentEntities(), associations, mock(ExcerptProjector.class)));
}
@Bean

View File

@@ -43,7 +43,6 @@ import org.springframework.data.rest.webmvc.EmbeddedResourcesAssembler;
import org.springframework.data.rest.webmvc.jpa.Person;
import org.springframework.data.rest.webmvc.jpa.PersonRepository;
import org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module.LookupObjectSerializer;
import org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module.NestedEntitySerializer;
import org.springframework.data.rest.webmvc.mapping.Associations;
import org.springframework.data.rest.webmvc.mapping.LinkCollector;
import org.springframework.data.rest.webmvc.spi.BackendIdConverter;
@@ -131,12 +130,10 @@ public class RepositoryTestsConfig {
Associations associations = new Associations(mappings, config());
LinkCollector collector = new LinkCollector(persistentEntities(), selfLinkProvider, associations);
NestedEntitySerializer nestedEntitySerializer = new NestedEntitySerializer(persistentEntities(),
new EmbeddedResourcesAssembler(persistentEntities(), associations, mock(ExcerptProjector.class)),
new ResourceProcessorInvoker(Collections.<ResourceProcessor<?>> emptyList()));
return new PersistentEntityJackson2Module(associations, persistentEntities(), uriToEntityConverter, collector,
invokerFactory, nestedEntitySerializer, mock(LookupObjectSerializer.class));
invokerFactory, mock(LookupObjectSerializer.class),
new ResourceProcessorInvoker(Collections.<ResourceProcessor<?>> emptyList()),
new EmbeddedResourcesAssembler(persistentEntities(), associations, mock(ExcerptProjector.class)));
}
@Bean

View File

@@ -25,6 +25,7 @@ import java.util.UUID;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Reference;
import org.springframework.data.rest.core.config.Projection;
/**
* @author Oliver Gierke
@@ -33,6 +34,11 @@ import org.springframework.data.annotation.Reference;
@EqualsAndHashCode(of = "id")
public class LineItem {
@Projection(name = "productsOnly", types = { LineItem.class })
public interface LineItemProductsOnlyProjection {
List<Product.ProductNameOnlyProjection> getProducts();
}
private final @Id UUID id = UUID.randomUUID();
private final String description;
private final BigDecimal price;

View File

@@ -23,12 +23,18 @@ import java.util.UUID;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Reference;
import org.springframework.data.rest.core.config.Projection;
/**
* @author Oliver Gierke
*/
@Value
public class Order {
@Projection(name = "itemsOnly", types = { Order.class })
public interface OrderItemsOnlyProjection {
List<LineItem.LineItemProductsOnlyProjection> getItems();
}
private final @Id UUID id = UUID.randomUUID();
private final List<LineItem> items = new ArrayList<>();

View File

@@ -22,6 +22,7 @@ import java.math.BigDecimal;
import java.util.UUID;
import org.springframework.data.annotation.Id;
import org.springframework.data.rest.core.config.Projection;
/**
* @author Oliver Gierke
@@ -31,6 +32,11 @@ import org.springframework.data.annotation.Id;
@RequiredArgsConstructor
public class Product {
@Projection(name = "nameOnly", types = { Product.class })
public interface ProductNameOnlyProjection {
String getName();
}
private final @Id UUID id = UUID.randomUUID();
private final String name;
private final BigDecimal price;

View File

@@ -58,6 +58,22 @@ public class ShopConfiguration {
};
}
@Bean
public ResourceProcessor<Resource<Product.ProductNameOnlyProjection>> productNameOnlyProjectionResourceProcessor() {
return new ResourceProcessor<Resource<Product.ProductNameOnlyProjection>>() {
/*
* (non-Javadoc)
* @see org.springframework.hateoas.ResourceProcessor#process(org.springframework.hateoas.ResourceSupport)
*/
@Override
public Resource<Product.ProductNameOnlyProjection> process(Resource<Product.ProductNameOnlyProjection> resource) {
resource.add(new Link("alpha", "beta"));
return resource;
}
};
}
@PostConstruct
public void init() {

View File

@@ -18,6 +18,9 @@ package org.springframework.data.rest.tests.shop;
import static org.hamcrest.CoreMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.data.rest.tests.AbstractWebIntegrationTests;
@@ -67,4 +70,36 @@ public class ShopIntegrationTests extends AbstractWebIntegrationTests {
actions.andExpect(jsonPath(prefix.concat("_links.").concat(suffix)).exists());
actions.andExpect(jsonPath(prefix.concat("_embedded.").concat(suffix)).exists());
}
@Test
public void renderProductNameOnlyProjection() throws Exception {
Map<String, Object> arguments = new HashMap<>();
arguments.put("projection", "nameOnly");
client.follow(client.discoverUnique("products").expand(arguments))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.products[0].name", notNullValue()))
.andExpect(jsonPath("$._embedded.products[0].price").doesNotExist());
}
@Test
public void renderProductNameOnlyProjectionResourceProcessor() throws Exception {
Map<String, Object> arguments = new HashMap<>();
arguments.put("projection", "nameOnly");
client.follow(client.discoverUnique("products").expand(arguments))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.products[0]._links.beta").exists());
}
/**
* @see DATAREST-221
*/
@Test
public void renderOrderItemsOnlyProjectionResourceProcessor() throws Exception {
Map<String, Object> arguments = new HashMap<>();
arguments.put("projection", "itemsOnly");
client.follow(client.discoverUnique("orders").expand(arguments))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.orders[0].items[0].products[0].name").exists())
.andExpect(jsonPath("$._embedded.orders[0].items[0].products[0]._links.beta").exists());
}
}