DATAREST-203 - Added test cases to show POSTs are generally working.
Some polishing in PersistentEntityResourceArgumentResolver.
This commit is contained in:
@@ -27,10 +27,11 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
* A Spring HATEOAS {@link Resource} subclass that holds a reference to the entity's {@link PersistentEntity} metadata.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class PersistentEntityResource<T> extends Resource<T> {
|
||||
|
||||
@JsonIgnore private final PersistentEntity<?, ?> entity;
|
||||
private final PersistentEntity<?, ?> entity;
|
||||
|
||||
public static <T> PersistentEntityResource<T> wrap(PersistentEntity<?, ?> entity, T obj) {
|
||||
return new PersistentEntityResource<T>(entity, obj);
|
||||
@@ -45,6 +46,7 @@ public class PersistentEntityResource<T> extends Resource<T> {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public PersistentEntity<?, ?> getPersistentEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
@@ -1,35 +1,79 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.rest.webmvc;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
/**
|
||||
* Custom {@link HandlerMethodArgumentResolver} to create {@link PersistentEntityResource} instances.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class PersistentEntityResourceHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
@Autowired private RepositoryRestRequestHandlerMethodArgumentResolver repoRequestResolver;
|
||||
private static final String ERROR_MESSAGE = "Could not read an object of type %s from the request! Converter %s returned null!";
|
||||
private static final String NO_CONVERTER_FOUND = "No suitable HttpMessageConverter found to read request body into object of type %s from request with content type of %s!";
|
||||
|
||||
private final RepositoryRestRequestHandlerMethodArgumentResolver repoRequestResolver;
|
||||
private final List<HttpMessageConverter<?>> messageConverters;
|
||||
|
||||
public PersistentEntityResourceHandlerMethodArgumentResolver(List<HttpMessageConverter<?>> messageConverters) {
|
||||
/**
|
||||
* Creates a new {@link PersistentEntityResourceHandlerMethodArgumentResolver} for the given
|
||||
* {@link HttpMessageConverter}s and {@link RepositoryRestRequestHandlerMethodArgumentResolver}..
|
||||
*
|
||||
* @param messageConverters must not be {@literal null}.
|
||||
* @param repositoryRequestResolver must not be {@literal null}.
|
||||
*/
|
||||
public PersistentEntityResourceHandlerMethodArgumentResolver(List<HttpMessageConverter<?>> messageConverters,
|
||||
RepositoryRestRequestHandlerMethodArgumentResolver repositoryRequestResolver) {
|
||||
|
||||
Assert.notEmpty(messageConverters, "MessageConverters must not be null or empty!");
|
||||
Assert.notNull(repositoryRequestResolver, "RepositoryRestRequestHandlerMethodArgumentResolver must not be empty!");
|
||||
|
||||
this.messageConverters = messageConverters;
|
||||
this.repoRequestResolver = repositoryRequestResolver;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.web.method.support.HandlerMethodArgumentResolver#supportsParameter(org.springframework.core.MethodParameter)
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return PersistentEntityResource.class.isAssignableFrom(parameter.getParameterType());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.web.method.support.HandlerMethodArgumentResolver#resolveArgument(org.springframework.core.MethodParameter, org.springframework.web.method.support.ModelAndViewContainer, org.springframework.web.context.request.NativeWebRequest, org.springframework.web.bind.support.WebDataBinderFactory)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
@@ -37,19 +81,27 @@ public class PersistentEntityResourceHandlerMethodArgumentResolver implements Ha
|
||||
RepositoryRestRequest repoRequest = (RepositoryRestRequest) repoRequestResolver.resolveArgument(parameter,
|
||||
mavContainer, webRequest, binderFactory);
|
||||
|
||||
final ServletServerHttpRequest request = new ServletServerHttpRequest(
|
||||
webRequest.getNativeRequest(HttpServletRequest.class));
|
||||
HttpServletRequest nativeRequest = webRequest.getNativeRequest(HttpServletRequest.class);
|
||||
ServletServerHttpRequest request = new ServletServerHttpRequest(nativeRequest);
|
||||
|
||||
Class<?> domainType = repoRequest.getPersistentEntity().getType();
|
||||
MediaType contentType = request.getHeaders().getContentType();
|
||||
|
||||
for (HttpMessageConverter converter : messageConverters) {
|
||||
Class<?> domainType = repoRequest.getPersistentEntity().getType();
|
||||
if (!converter.canRead(domainType, request.getHeaders().getContentType())) {
|
||||
|
||||
if (!converter.canRead(domainType, contentType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object obj = converter.read(domainType, request);
|
||||
|
||||
if (obj == null) {
|
||||
throw new HttpMessageNotReadableException(String.format(ERROR_MESSAGE, domainType, converter));
|
||||
}
|
||||
|
||||
return new PersistentEntityResource<Object>(repoRequest.getPersistentEntity(), obj);
|
||||
}
|
||||
|
||||
return null;
|
||||
throw new HttpMessageNotReadableException(String.format(NO_CONVERTER_FOUND, domainType, contentType));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -254,10 +254,11 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
|
||||
*/
|
||||
@Bean
|
||||
public PersistentEntityResourceHandlerMethodArgumentResolver persistentEntityArgumentResolver() {
|
||||
|
||||
List<HttpMessageConverter<?>> messageConverters = defaultMessageConverters();
|
||||
configureHttpMessageConverters(messageConverters);
|
||||
|
||||
return new PersistentEntityResourceHandlerMethodArgumentResolver(messageConverters);
|
||||
return new PersistentEntityResourceHandlerMethodArgumentResolver(messageConverters, repoRequestArgumentResolver());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -432,7 +433,8 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
|
||||
return new DefaultRepositoryInvokerFactory(repositories(), defaultConversionService());
|
||||
}
|
||||
|
||||
private List<HttpMessageConverter<?>> defaultMessageConverters() {
|
||||
@Bean
|
||||
public List<HttpMessageConverter<?>> defaultMessageConverters() {
|
||||
|
||||
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||
|
||||
|
||||
@@ -17,10 +17,13 @@ package org.springframework.data.rest.webmvc;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -40,6 +43,7 @@ import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultActions;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
@@ -272,5 +276,34 @@ public abstract class AbstractWebIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postsPayloadToResource() throws Exception {
|
||||
|
||||
Map<String, String> payloads = getPayloadToPost();
|
||||
assumeFalse(payloads.isEmpty());
|
||||
|
||||
MockHttpServletResponse response = request("/");
|
||||
|
||||
for (String rel : expectedRootLinkRels()) {
|
||||
|
||||
String payload = payloads.get(rel);
|
||||
|
||||
if (payload != null) {
|
||||
Link link = assertHasLinkWithRel(rel, response);
|
||||
|
||||
MockHttpServletRequestBuilder request = post(link.getHref()).//
|
||||
content(payload).//
|
||||
contentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
mvc.perform(request). //
|
||||
andExpect(status().isCreated());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Iterable<String> expectedRootLinkRels();
|
||||
|
||||
protected Map<String, String> getPayloadToPost() throws Exception {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -72,6 +74,15 @@ public class JpaWebTests extends AbstractWebIntegrationTests {
|
||||
return Arrays.asList("people");
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.rest.webmvc.AbstractWebIntegrationTests#getPayloadToPost()
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, String> getPayloadToPost() throws Exception {
|
||||
return Collections.singletonMap("people", readFile("person.json"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-99
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{ "firstName" : "Dave",
|
||||
"lastName" : "Matthews"
|
||||
}
|
||||
Reference in New Issue
Block a user