Remove JSONP support from the controllers in preference to a forthcoming JSONP Servlet Filter to implement the functionality on a wider scale.

This commit is contained in:
Jon Brisbin
2013-03-06 07:56:48 -06:00
parent 05f11a6cf9
commit 35a4846590
9 changed files with 2 additions and 370 deletions

View File

@@ -189,7 +189,7 @@ project("spring-data-rest-repository") {
compile("org.springframework.data:spring-data-mongodb:$sdMongoVersion", optional)
// JSR 303 Validation
compile "javax.validation:validation-api:1.0.0.GA"
compile("javax.validation:validation-api:1.0.0.GA", optional)
// Testing
testCompile "org.hsqldb:hsqldb:$hsqldbVersion"

View File

@@ -33,7 +33,6 @@ import org.springframework.data.rest.repository.support.ResourceMappingUtils;
import org.springframework.data.rest.webmvc.support.BaseUriLinkBuilder;
import org.springframework.data.rest.webmvc.support.ConstraintViolationExceptionMessage;
import org.springframework.data.rest.webmvc.support.ExceptionMessage;
import org.springframework.data.rest.webmvc.support.JsonpResponse;
import org.springframework.data.rest.webmvc.support.RepositoryConstraintViolationExceptionMessage;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.Link;
@@ -230,39 +229,6 @@ public class AbstractRepositoryRestController implements ApplicationContextAware
return new ResponseEntity<Resource<?>>(resource, hdrs, status);
}
protected <T> JsonpResponse<T> jsonpWrapResponse(RepositoryRestRequest repoRequest,
T response,
HttpStatus status) {
return jsonpWrapResponse(repoRequest, response, null, status);
}
protected <T> JsonpResponse<T> jsonpWrapResponse(RepositoryRestRequest repoRequest,
ResponseEntity<T> response) {
return jsonpWrapResponse(repoRequest,
response.getBody(),
response.getHeaders(),
response.getStatusCode());
}
protected <T> JsonpResponse<T> jsonpWrapResponse(RepositoryRestRequest repoRequest,
T response,
HttpHeaders headers,
HttpStatus status) {
String callback = repoRequest.getRequest().getParameter(config.getJsonpParamName());
String errback = (null != config.getJsonpOnErrParamName()
? repoRequest.getRequest().getParameter(config.getJsonpOnErrParamName())
: null);
ResponseEntity<T> newResponse;
if(null != headers) {
newResponse = new ResponseEntity<T>(response, headers, status);
} else {
newResponse = new ResponseEntity<T>(response, status);
}
return new JsonpResponse<T>(newResponse,
(null != callback ? callback : config.getJsonpParamName()),
(null != errback ? errback : config.getJsonpOnErrParamName()));
}
protected List<Link> queryMethodLinks(URI baseUri, Class<?> domainType) {
List<Link> links = new ArrayList<Link>();
RepositoryInformation repoInfo = repositories.getRepositoryInformationFor(domainType);

View File

@@ -7,10 +7,8 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.data.repository.support.DomainClassConverter;
import org.springframework.data.repository.support.Repositories;
import org.springframework.data.rest.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.support.JsonpResponse;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -53,16 +51,4 @@ public class RepositoryController extends AbstractRepositoryRestController {
return links;
}
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<? extends Resource<?>> jsonpListRepositories(RepositoryRestRequest repoRequest)
throws ResourceNotFoundException {
return jsonpWrapResponse(repoRequest, listRepositories(), HttpStatus.OK);
}
}

View File

@@ -28,7 +28,6 @@ import org.springframework.data.rest.repository.invoke.RepositoryMethodInvoker;
import org.springframework.data.rest.repository.json.JsonSchema;
import org.springframework.data.rest.repository.json.PersistentEntityToJsonSchemaConverter;
import org.springframework.data.rest.repository.support.DomainObjectMerger;
import org.springframework.data.rest.webmvc.support.JsonpResponse;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.Resource;
@@ -128,18 +127,6 @@ public class RepositoryEntityController extends AbstractRepositoryRestController
return new Resources<Resource<?>>(resources, links);
}
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<? extends Resources<Resource<?>>> jsonpListEntities(RepositoryRestRequest repoRequest)
throws ResourceNotFoundException {
return jsonpWrapResponse(repoRequest, listEntities(repoRequest), HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = RequestMethod.GET,
@@ -203,22 +190,6 @@ public class RepositoryEntityController extends AbstractRepositoryRestController
}
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = RequestMethod.POST,
consumes = {
"application/json"
},
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<? extends Resource<?>> jsonpCreateNewEntity(RepositoryRestRequest repoRequest,
PersistentEntityResource<?> incoming) {
return jsonpWrapResponse(repoRequest, createNewEntity(repoRequest, incoming));
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{id}",
@@ -253,23 +224,6 @@ public class RepositoryEntityController extends AbstractRepositoryRestController
return per;
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{id}",
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<? extends Resource<?>> jsonpGetSingleEntity(RepositoryRestRequest repoRequest,
@PathVariable String id)
throws ResourceNotFoundException {
return jsonpWrapResponse(repoRequest,
getSingleEntity(repoRequest, id),
HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{id}",
@@ -324,25 +278,6 @@ public class RepositoryEntityController extends AbstractRepositoryRestController
}
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{id}",
method = RequestMethod.PUT,
consumes = {
"application/json"
},
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<? extends Resource<?>> jsonpUpdateEntity(RepositoryRestRequest repoRequest,
PersistentEntityResource<?> incoming,
@PathVariable String id)
throws ResourceNotFoundException {
return jsonpWrapResponse(repoRequest, updateEntity(repoRequest, incoming, id));
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{id}",
@@ -381,19 +316,4 @@ public class RepositoryEntityController extends AbstractRepositoryRestController
return new ResponseEntity<Object>(HttpStatus.NO_CONTENT);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "{id}",
method = RequestMethod.DELETE,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpDeleteEntity(RepositoryRestRequest repoRequest,
@PathVariable String id)
throws ResourceNotFoundException {
return jsonpWrapResponse(repoRequest, deleteEntity(repoRequest, id));
}
}

View File

@@ -27,7 +27,6 @@ import org.springframework.data.rest.repository.context.AfterLinkSaveEvent;
import org.springframework.data.rest.repository.context.BeforeLinkDeleteEvent;
import org.springframework.data.rest.repository.context.BeforeLinkSaveEvent;
import org.springframework.data.rest.repository.invoke.RepositoryMethodInvoker;
import org.springframework.data.rest.webmvc.support.JsonpResponse;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.Resource;
@@ -241,47 +240,6 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes
return resourceResponse(null, new Resource<Object>(EMPTY_RESOURCE_LIST, links), HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpFollowPropertyReference(RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException {
return jsonpWrapResponse(repoRequest,
followPropertyReference(repoRequest,
id,
property),
HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{propertyId}",
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpFollowPropertyReference(RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property,
@PathVariable String propertyId)
throws ResourceNotFoundException, NoSuchMethodException {
return jsonpWrapResponse(repoRequest,
followPropertyReference(repoRequest,
id,
property,
propertyId),
HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = {
@@ -352,28 +310,6 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes
return resourceResponse(null, EMPTY_RESOURCE, HttpStatus.CREATED);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
method = {
RequestMethod.POST,
RequestMethod.PUT
},
consumes = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpCreatePropertyReference(final RepositoryRestRequest repoRequest,
final @RequestBody Resource<Object> incoming,
@PathVariable String id,
@PathVariable String property)
throws ResourceNotFoundException, NoSuchMethodException {
return jsonpWrapResponse(repoRequest, createPropertyReference(repoRequest,
incoming,
id,
property));
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{propertyId}",
@@ -433,26 +369,6 @@ public class RepositoryPropertyReferenceController extends AbstractRepositoryRes
return resourceResponse(null, EMPTY_RESOURCE, HttpStatus.NO_CONTENT);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{propertyId}",
method = RequestMethod.DELETE,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpDeletePropertyReference(final RepositoryRestRequest repoRequest,
@PathVariable String id,
@PathVariable String property,
final @PathVariable String propertyId)
throws ResourceNotFoundException, NoSuchMethodException {
return jsonpWrapResponse(repoRequest, deletePropertyReference(repoRequest,
id,
property,
propertyId));
}
private Link propertyReferenceLink(Resource<?> resource,
URI baseUri,
String rel) {

View File

@@ -21,11 +21,9 @@ import org.springframework.data.rest.repository.BaseUriAwareResource;
import org.springframework.data.rest.repository.PersistentEntityResource;
import org.springframework.data.rest.repository.invoke.RepositoryMethod;
import org.springframework.data.rest.repository.invoke.RepositoryMethodInvoker;
import org.springframework.data.rest.webmvc.support.JsonpResponse;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -66,17 +64,6 @@ public class RepositorySearchController extends AbstractRepositoryRestController
return new Resource<Object>(Collections.emptyList(), links);
}
@RequestMapping(
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<?> jsonpList(RepositoryRestRequest repoRequest) {
return jsonpWrapResponse(repoRequest, list(repoRequest), HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
@RequestMapping(
value = "/{method}",
@@ -206,20 +193,6 @@ public class RepositorySearchController extends AbstractRepositoryRestController
return new Resource<Object>(EMPTY_RESOURCE_LIST, links);
}
@RequestMapping(
value = "/{method}",
method = RequestMethod.GET,
produces = {
"application/javascript"
}
)
@ResponseBody
public JsonpResponse<? extends Resource<?>> jsonpQuery(RepositoryRestRequest repoRequest,
@PathVariable String method)
throws ResourceNotFoundException {
return jsonpWrapResponse(repoRequest, query(repoRequest, method), HttpStatus.OK);
}
@SuppressWarnings({"unchecked"})
private BaseUriAwareResource entitiesToResource(RepositoryRestRequest repoRequest, Iterable entities) {
List<Resource<?>> resources = new ArrayList<Resource<?>>();

View File

@@ -23,7 +23,6 @@ import org.springframework.data.rest.repository.json.Jackson2DatatypeHelper;
import org.springframework.data.rest.repository.json.PersistentEntityJackson2Module;
import org.springframework.data.rest.repository.json.PersistentEntityToJsonSchemaConverter;
import org.springframework.data.rest.repository.support.DomainObjectMerger;
import org.springframework.data.rest.webmvc.support.RepositoryEntityLinks;
import org.springframework.data.rest.webmvc.BaseUriMethodArgumentResolver;
import org.springframework.data.rest.webmvc.PagingAndSortingMethodArgumentResolver;
import org.springframework.data.rest.webmvc.PersistentEntityResourceHandlerMethodArgumentResolver;
@@ -36,8 +35,8 @@ import org.springframework.data.rest.webmvc.RepositoryRestHandlerMapping;
import org.springframework.data.rest.webmvc.RepositoryRestRequestHandlerMethodArgumentResolver;
import org.springframework.data.rest.webmvc.RepositorySearchController;
import org.springframework.data.rest.webmvc.ServerHttpRequestMethodArgumentResolver;
import org.springframework.data.rest.webmvc.convert.JsonpResponseHttpMessageConverter;
import org.springframework.data.rest.webmvc.convert.UriListHttpMessageConverter;
import org.springframework.data.rest.webmvc.support.RepositoryEntityLinks;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.hateoas.EntityLinks;
import org.springframework.http.MediaType;
@@ -314,15 +313,6 @@ public class RepositoryRestMvcConfiguration {
return jacksonConverter;
}
/**
* The {@link HttpMessageConverter} used to create JSONP responses.
*
* @return
*/
@Bean public JsonpResponseHttpMessageConverter jsonpHttpMessageConverter() {
return new JsonpResponseHttpMessageConverter(jacksonHttpMessageConverter());
}
/**
* The {@link HttpMessageConverter} used to create {@literal text/uri-list} responses.
*
@@ -389,7 +379,6 @@ public class RepositoryRestMvcConfiguration {
private List<HttpMessageConverter<?>> defaultMessageConverters() {
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
messageConverters.add(jacksonHttpMessageConverter());
messageConverters.add(jsonpHttpMessageConverter());
messageConverters.add(uriListHttpMessageConverter());
return messageConverters;
}

View File

@@ -1,84 +0,0 @@
package org.springframework.data.rest.webmvc.convert;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import org.springframework.data.rest.webmvc.support.JsonpResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
/**
* @author Jon Brisbin
*/
public class JsonpResponseHttpMessageConverter implements HttpMessageConverter<JsonpResponse<?>> {
private static final MediaType APPLICATION_JAVASCRIPT = MediaType.valueOf("application/javascript");
private static final List<MediaType> SUPPORTED_TYPES = Arrays.asList(
APPLICATION_JAVASCRIPT
);
private final MappingJackson2HttpMessageConverter jacksonConverter;
public JsonpResponseHttpMessageConverter(MappingJackson2HttpMessageConverter jacksonConverter) {
this.jacksonConverter = jacksonConverter;
}
@Override public boolean canRead(Class<?> clazz, MediaType mediaType) {
return false;
}
@Override public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return JsonpResponse.class.isAssignableFrom(clazz) && mediaType.getSubtype().contains("javascript");
}
@Override public List<MediaType> getSupportedMediaTypes() {
return SUPPORTED_TYPES;
}
@Override
public JsonpResponse<?> read(Class<? extends JsonpResponse<?>> clazz,
HttpInputMessage inputMessage) throws IOException,
HttpMessageNotReadableException {
throw new HttpMessageNotReadableException("JSONP messages are not readable.");
}
@Override
public void write(JsonpResponse<?> jsonpResponse,
MediaType contentType,
final HttpOutputMessage outputMessage) throws IOException,
HttpMessageNotWritableException {
final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bytes.write((jsonpResponse.getCallbackParam() + "(").getBytes());
jacksonConverter.write(jsonpResponse.getResponseEntity().getBody(),
MediaType.APPLICATION_JSON,
new HttpOutputMessage() {
@Override public OutputStream getBody() throws IOException {
return bytes;
}
@Override public HttpHeaders getHeaders() {
return outputMessage.getHeaders();
}
});
bytes.write(");".getBytes());
byte[] byteArray = bytes.toByteArray();
outputMessage.getHeaders().setContentType(APPLICATION_JAVASCRIPT);
outputMessage.getHeaders().setContentLength(byteArray.length);
outputMessage.getBody().flush();
outputMessage.getBody().write(byteArray);
}
}

View File

@@ -1,34 +0,0 @@
package org.springframework.data.rest.webmvc.support;
import org.springframework.http.ResponseEntity;
/**
* @author Jon Brisbin
*/
public class JsonpResponse<T> {
private final ResponseEntity<T> responseEntity;
private final String callbackParam;
private final String errbackParam;
public JsonpResponse(ResponseEntity<T> responseEntity,
String callbackParam,
String errbackParam) {
this.responseEntity = responseEntity;
this.callbackParam = callbackParam;
this.errbackParam = errbackParam;
}
public ResponseEntity<T> getResponseEntity() {
return responseEntity;
}
public String getCallbackParam() {
return callbackParam;
}
public String getErrbackParam() {
return errbackParam;
}
}