diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BaseUriMethodArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BaseUriMethodArgumentResolver.java new file mode 100644 index 000000000..649f7eac4 --- /dev/null +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BaseUriMethodArgumentResolver.java @@ -0,0 +1,47 @@ +package org.springframework.data.rest.webmvc; + +import java.net.URI; +import javax.servlet.http.HttpServletRequest; + +import org.springframework.core.MethodParameter; +import org.springframework.data.rest.webmvc.json.JsonSchemaController; +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; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +/** + * @author Jon Brisbin + */ +public class BaseUriMethodArgumentResolver implements HandlerMethodArgumentResolver { + + private RepositoryRestConfiguration config; + + public BaseUriMethodArgumentResolver(RepositoryRestConfiguration config) { + this.config = config; + } + + @Override public boolean supportsParameter(MethodParameter parameter) { + return (RepositoryRestController.class.isAssignableFrom(parameter.getDeclaringClass()) + || JsonSchemaController.class.isAssignableFrom(parameter.getDeclaringClass())) + && parameter.getParameterType() == URI.class; + } + + @Override + public Object resolveArgument(MethodParameter parameter, + ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, + WebDataBinderFactory binderFactory) throws Exception { + HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class); + + // Use configured URI if there is one or set the current one as the default if not. + if(null == config.getBaseUri()) { + URI baseUri = ServletUriComponentsBuilder.fromServletMapping(servletRequest).build().toUri(); + config.setBaseUri(baseUri); + } + + return config.getBaseUri(); + } + +} diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/EntityToResourceConverter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/EntityToResourceConverter.java index 9457878ab..011fe82ce 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/EntityToResourceConverter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/EntityToResourceConverter.java @@ -26,10 +26,13 @@ import org.springframework.util.Assert; */ public class EntityToResourceConverter implements Converter { - private final RepositoryMetadata repositoryMetadata; - private final EntityMetadata entityMetadata; + private final RepositoryRestConfiguration config; + private final RepositoryMetadata repositoryMetadata; + private final EntityMetadata entityMetadata; - public EntityToResourceConverter(RepositoryMetadata repositoryMetadata) { + public EntityToResourceConverter(RepositoryRestConfiguration config, + RepositoryMetadata repositoryMetadata) { + this.config = config; Assert.notNull(repositoryMetadata, "RepositoryMetadata cannot be null!"); this.repositoryMetadata = repositoryMetadata; this.entityMetadata = repositoryMetadata.entityMetadata(); @@ -41,9 +44,8 @@ public class EntityToResourceConverter implements Converter { return new Resource(source); } - URI baseUri = RepositoryRestController.BASE_URI.get(); Serializable id = (Serializable)repositoryMetadata.entityMetadata().idAttribute().get(source); - URI selfUri = buildUri(baseUri, repositoryMetadata.name(), id.toString()); + URI selfUri = buildUri(config.getBaseUri(), repositoryMetadata.name(), id.toString()); Set links = new HashSet(); for(Object attrName : entityMetadata.linkedAttributes().keySet()) { diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryAwareMappingHttpMessageConverter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryAwareMappingHttpMessageConverter.java index bc8e3ae93..66a52f6c4 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryAwareMappingHttpMessageConverter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryAwareMappingHttpMessageConverter.java @@ -62,9 +62,16 @@ public class RepositoryAwareMappingHttpMessageConverter } @Override public void afterPropertiesSet() throws Exception { - //mapper.registerModule(jacksonModule); + boolean builtInModuleRegistered = false; for(Module m : modules) { mapper.registerModule(m); + if(m.getClass() == RepositoryAwareJacksonModule.class) { + builtInModuleRegistered = true; + } + } + + if(!builtInModuleRegistered) { + mapper.registerModule(jacksonModule); } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestConfiguration.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestConfiguration.java index 59e5a85c1..321d58299 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestConfiguration.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestConfiguration.java @@ -1,5 +1,6 @@ package org.springframework.data.rest.webmvc; +import java.net.URI; import java.util.Collections; import java.util.List; import java.util.Map; @@ -18,6 +19,7 @@ public class RepositoryRestConfiguration { public static final RepositoryRestConfiguration DEFAULT = new RepositoryRestConfiguration(); + private URI baseUri = null; private int defaultPageSize = 20; private String pageParamName = "page"; private String limitParamName = "limit"; @@ -29,6 +31,26 @@ public class RepositoryRestConfiguration { private MediaType defaultMediaType = MediaType.APPLICATION_JSON; private boolean dumpErrors = true; + /** + * The base URI against which the exporter should calculate its links. + * + * @return + */ + public URI getBaseUri() { + return baseUri; + } + + /** + * The base URI against which the exporter should calculate its links. + * + * @param baseUri + */ + public RepositoryRestConfiguration setBaseUri(URI baseUri) { + Assert.notNull(baseUri, "The baseUri cannot be null."); + this.baseUri = baseUri; + return this; + } + /** * Get the default size of {@link org.springframework.data.domain.Pageable}s. Default is 20. * diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java index 90ab3898e..c69d05545 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java @@ -129,9 +129,9 @@ public class RepositoryRestController implements ApplicationContextAware, InitializingBean { - public static final String LOCATION = "Location"; - public static final String SELF = "self"; - public static final ThreadLocal BASE_URI = new ThreadLocal(); + public static final String LOCATION = "Location"; + public static final String SELF = "self"; + //public static final ThreadLocal BASE_URI = new ThreadLocal(); private static final Logger LOG = LoggerFactory.getLogger( RepositoryRestController.class); @@ -332,7 +332,7 @@ public class RepositoryRestController for(String repoName : (Set)exp.repositoryNames()) { RepositoryMetadata repoMeta = exp.repositoryMetadataFor(repoName); Class domainType = repoMeta.domainType(); - entityConverters.addConverter(domainType, Resource.class, new EntityToResourceConverter(repoMeta)); + entityConverters.addConverter(domainType, Resource.class, new EntityToResourceConverter(config, repoMeta)); } } conversionService.addConversionServices(entityConverters); @@ -342,7 +342,7 @@ public class RepositoryRestController * List available {@link CrudRepository}s that are being exported. * * @param request - * @param uriBuilder + * @param baseUri * * @return * @@ -355,10 +355,7 @@ public class RepositoryRestController ) @ResponseBody public ResponseEntity listRepositories(ServletServerHttpRequest request, - UriComponentsBuilder uriBuilder) throws IOException { - URI baseUri = uriBuilder.build().toUri(); - BASE_URI.set(baseUri); - + URI baseUri) throws IOException { List links = new ArrayList(); for(RepositoryExporter repoExporter : repositoryExporters) { for(String name : (Set)repoExporter.repositoryNames()) { @@ -382,7 +379,7 @@ public class RepositoryRestController * * @param request * @param pageSort - * @param uriBuilder + * @param baseUri * @param repository * * @return @@ -397,11 +394,8 @@ public class RepositoryRestController @ResponseBody public ResponseEntity listEntities(ServletServerHttpRequest request, PagingAndSorting pageSort, - UriComponentsBuilder uriBuilder, + URI baseUri, @PathVariable String repository) throws IOException { - URI baseUri = uriBuilder.build().toUri(); - BASE_URI.set(baseUri); - RepositoryMetadata repoMeta = repositoryMetadataFor(repository); if(!repoMeta.exportsMethod(CrudMethod.FIND_ALL)) { return negotiateResponse(request, HttpStatus.METHOD_NOT_ALLOWED, new HttpHeaders(), null); @@ -492,7 +486,7 @@ public class RepositoryRestController * List the URIs of query methods found on this repository interface. * * @param request - * @param uriBuilder + * @param baseUri * @param repository * * @return @@ -506,11 +500,8 @@ public class RepositoryRestController ) @ResponseBody public ResponseEntity listQueryMethods(ServletServerHttpRequest request, - UriComponentsBuilder uriBuilder, + URI baseUri, @PathVariable String repository) throws IOException { - URI baseUri = uriBuilder.build().toUri(); - BASE_URI.set(baseUri); - RepositoryMetadata repoMeta = repositoryMetadataFor(repository); Set links = new HashSet(); @@ -550,7 +541,7 @@ public class RepositoryRestController * * @param request * @param pageSort - * @param uriBuilder + * @param baseUri * @param repository * @param query * @@ -568,14 +559,11 @@ public class RepositoryRestController @ResponseBody public ResponseEntity query(ServletServerHttpRequest request, PagingAndSorting pageSort, - UriComponentsBuilder uriBuilder, + URI baseUri, @PathVariable String repository, @PathVariable String query) throws InvocationTargetException, IllegalAccessException, IOException { - URI baseUri = uriBuilder.build().toUri(); - BASE_URI.set(baseUri); - RepositoryMetadata repoMeta = repositoryMetadataFor(repository); Repository repo = repoMeta.repository(); RepositoryQueryMethod queryMethod = repoMeta.queryMethod(query); @@ -728,7 +716,7 @@ public class RepositoryRestController * To get the entity back in the body of the response, simpy add the URL parameter
returnBody=true
. * * @param request - * @param uriBuilder + * @param baseUri * @param repository * * @return @@ -742,11 +730,8 @@ public class RepositoryRestController ) @ResponseBody public ResponseEntity create(ServletServerHttpRequest request, - UriComponentsBuilder uriBuilder, + URI baseUri, @PathVariable String repository) throws IOException { - URI baseUri = uriBuilder.build().toUri(); - BASE_URI.set(baseUri); - RepositoryMetadata repoMeta = repositoryMetadataFor(repository); if(!repoMeta.exportsMethod(CrudMethod.SAVE_ONE)) { return negotiateResponse(request, HttpStatus.METHOD_NOT_ALLOWED, new HttpHeaders(), null); @@ -783,7 +768,7 @@ public class RepositoryRestController * Retrieve a specific entity. * * @param request - * @param uriBuilder + * @param baseUri * @param repository * @param id * @@ -798,12 +783,9 @@ public class RepositoryRestController ) @ResponseBody public ResponseEntity entity(ServletServerHttpRequest request, - UriComponentsBuilder uriBuilder, + URI baseUri, @PathVariable String repository, @PathVariable String id) throws IOException { - URI baseUri = uriBuilder.build().toUri(); - BASE_URI.set(baseUri); - RepositoryMetadata repoMeta = repositoryMetadataFor(repository); if(!repoMeta.exportsMethod(CrudMethod.FIND_ONE)) { return negotiateResponse(request, HttpStatus.METHOD_NOT_ALLOWED, new HttpHeaders(), null); @@ -842,7 +824,7 @@ public class RepositoryRestController * Create an entity with a specific ID or update an existing entity. * * @param request - * @param uriBuilder + * @param baseUri * @param repository * @param id * @@ -861,14 +843,11 @@ public class RepositoryRestController ) @ResponseBody public ResponseEntity createOrUpdate(ServletServerHttpRequest request, - UriComponentsBuilder uriBuilder, + URI baseUri, @PathVariable String repository, @PathVariable String id) throws IOException, IllegalAccessException, InstantiationException { - URI baseUri = uriBuilder.build().toUri(); - BASE_URI.set(baseUri); - RepositoryMetadata repoMeta = repositoryMetadataFor(repository); if(!repoMeta.exportsMethod(CrudMethod.SAVE_ONE) || !repoMeta.exportsMethod(CrudMethod.FIND_ONE)) { return negotiateResponse(request, HttpStatus.METHOD_NOT_ALLOWED, new HttpHeaders(), null); @@ -979,7 +958,7 @@ public class RepositoryRestController * Retrieve the property of an entity. * * @param request - * @param uriBuilder + * @param baseUri * @param repository * @param id * @param property @@ -995,12 +974,10 @@ public class RepositoryRestController ) @ResponseBody public ResponseEntity propertyOfEntity(ServletServerHttpRequest request, - UriComponentsBuilder uriBuilder, + URI baseUri, @PathVariable String repository, @PathVariable String id, @PathVariable String property) throws IOException { - URI baseUri = uriBuilder.build().toUri(); - BASE_URI.set(baseUri); String accept = request.getServletRequest().getHeader("Accept"); RepositoryMetadata repoMeta = repositoryMetadataFor(repository); @@ -1138,7 +1115,7 @@ public class RepositoryRestController * Update the property of an entity if that property is also managed by a {@link CrudRepository}. * * @param request - * @param uriBuilder + * @param baseUri * @param repository * @param id * @param property @@ -1157,12 +1134,10 @@ public class RepositoryRestController ) @ResponseBody public ResponseEntity updatePropertyOfEntity(final ServletServerHttpRequest request, - UriComponentsBuilder uriBuilder, + URI baseUri, @PathVariable String repository, @PathVariable String id, final @PathVariable String property) throws IOException { - URI baseUri = uriBuilder.build().toUri(); - BASE_URI.set(baseUri); final RepositoryMetadata repoMeta = repositoryMetadataFor(repository); if(!repoMeta.exportsMethod(CrudMethod.SAVE_ONE)) { @@ -1317,7 +1292,7 @@ public class RepositoryRestController * Retrieve a linked entity from a parent entity. * * @param request - * @param uriBuilder + * @param baseUri * @param repository * @param id * @param property @@ -1336,14 +1311,11 @@ public class RepositoryRestController ) @ResponseBody public ResponseEntity linkedEntity(ServletServerHttpRequest request, - UriComponentsBuilder uriBuilder, + URI baseUri, @PathVariable String repository, @PathVariable String id, @PathVariable String property, @PathVariable String linkedId) throws IOException { - URI baseUri = uriBuilder.build().toUri(); - BASE_URI.set(baseUri); - RepositoryMetadata repoMeta = repositoryMetadataFor(repository); if(!repoMeta.exportsMethod(CrudMethod.FIND_ONE)) { return negotiateResponse(request, HttpStatus.METHOD_NOT_ALLOWED, new HttpHeaders(), null); @@ -1774,7 +1746,7 @@ public class RepositoryRestController } else if(null != (repoMeta = repositoryMetadataFor(obj.getClass()))) { AttributeMetadata attrMeta = repoMeta.entityMetadata().idAttribute(); String id = attrMeta.get(obj).toString(); - key = "@" + buildUri(BASE_URI.get(), repoMeta.name(), id); + key = "@" + buildUri(config.getBaseUri(), repoMeta.name(), id); } else { key = conversionService.convert(obj, String.class); } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerAdapter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerAdapter.java index bb1602b4e..d2e5b2bad 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerAdapter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerAdapter.java @@ -20,6 +20,7 @@ public class RepositoryRestHandlerAdapter extends ResourceProcessorInvokingHandl public RepositoryRestHandlerAdapter(RepositoryRestConfiguration config) { setCustomArgumentResolvers(Arrays.asList( new ServerHttpRequestMethodArgumentResolver(), + new BaseUriMethodArgumentResolver(config), new PagingAndSortingMethodArgumentResolver(config) )); } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/JsonSchemaController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/JsonSchemaController.java index c1e38e157..a8434ca7e 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/JsonSchemaController.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/JsonSchemaController.java @@ -8,7 +8,6 @@ import org.codehaus.jackson.map.SerializationConfig; import org.codehaus.jackson.schema.JsonSchema; import org.springframework.data.rest.repository.RepositoryExporterSupport; import org.springframework.data.rest.repository.RepositoryMetadata; -import org.springframework.data.rest.webmvc.RepositoryRestController; import org.springframework.hateoas.Link; import org.springframework.hateoas.Resource; import org.springframework.http.HttpStatus; @@ -40,11 +39,8 @@ public class JsonSchemaController extends RepositoryExporterSupport schemaForRepository(ServletServerHttpRequest request, - UriComponentsBuilder uriBuilder, + URI baseUri, @PathVariable String repository) throws IOException { - URI baseUri = uriBuilder.build().toUri(); - RepositoryRestController.BASE_URI.set(baseUri); - RepositoryMetadata repoMeta = repositoryMetadataFor(repository); if(null == repoMeta) { throw new IllegalArgumentException("Resource /" + repository + "/schema not found."); diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/RepositoryAwareJacksonModule.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/RepositoryAwareJacksonModule.java index beac8cb4f..3f523578b 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/RepositoryAwareJacksonModule.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/json/RepositoryAwareJacksonModule.java @@ -42,7 +42,7 @@ import org.springframework.data.rest.repository.RepositoryExporter; import org.springframework.data.rest.repository.RepositoryMetadata; import org.springframework.data.rest.repository.UriToDomainObjectUriResolver; import org.springframework.data.rest.webmvc.EntityToResourceConverter; -import org.springframework.data.rest.webmvc.RepositoryRestController; +import org.springframework.data.rest.webmvc.RepositoryRestConfiguration; import org.springframework.data.util.TypeInformation; import org.springframework.hateoas.Link; import org.springframework.hateoas.Resource; @@ -57,6 +57,8 @@ import org.springframework.http.converter.HttpMessageNotReadableException; */ public class RepositoryAwareJacksonModule extends SimpleModule implements InitializingBean { + @Autowired + private RepositoryRestConfiguration config; @Autowired(required = false) protected List repositoryExporters = Collections.emptyList(); @Autowired(required = false) @@ -97,7 +99,7 @@ public class RepositoryAwareJacksonModule extends SimpleModule implements Initia } } - conversionService.addConverter(domainType, Resource.class, new EntityToResourceConverter(repoMeta)); + conversionService.addConverter(domainType, Resource.class, new EntityToResourceConverter(config, repoMeta)); sers.addSerializer(domainType, new DomainObjectToResourceSerializer(domainType)); keySers.addSerializer(domainType, new DomainObjectToStringKeySerializer(domainType, repoMeta)); @@ -206,7 +208,7 @@ public class RepositoryAwareJacksonModule extends SimpleModule implements Initia sId = serId.toString(); } - URI href = buildUri(RepositoryRestController.BASE_URI.get(), repoMeta.name(), sId); + URI href = buildUri(config.getBaseUri(), repoMeta.name(), sId); jgen.writeString("@" + href.toString()); } @@ -237,7 +239,7 @@ public class RepositoryAwareJacksonModule extends SimpleModule implements Initia if(name.startsWith("@http")) { entity = domainObjectResolver.resolve( - RepositoryRestController.BASE_URI.get(), + config.getBaseUri(), URI.create(name.substring(1)) ); continue; @@ -245,7 +247,7 @@ public class RepositoryAwareJacksonModule extends SimpleModule implements Initia if("href".equals(name)) { entity = domainObjectResolver.resolve( - RepositoryRestController.BASE_URI.get(), + config.getBaseUri(), URI.create(jp.nextTextValue()) ); continue; @@ -327,7 +329,7 @@ public class RepositoryAwareJacksonModule extends SimpleModule implements Initia Object mkey = ( name.startsWith("@http") ? domainObjectResolver.resolve( - RepositoryRestController.BASE_URI.get(), + config.getBaseUri(), URI.create(name.substring(1)) ) : name @@ -371,7 +373,7 @@ public class RepositoryAwareJacksonModule extends SimpleModule implements Initia JsonProcessingException { if(key.startsWith("@http")) { return domainObjectResolver.resolve( - RepositoryRestController.BASE_URI.get(), + config.getBaseUri(), URI.create(key.substring(1)) ); } else { diff --git a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/BaseSpec.groovy b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/BaseSpec.groovy index 3c80a80ea..17e17b763 100644 --- a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/BaseSpec.groovy +++ b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/BaseSpec.groovy @@ -9,7 +9,9 @@ import org.springframework.data.rest.test.webmvc.ApplicationConfig import org.springframework.data.rest.test.webmvc.CustomerRepository import org.springframework.data.rest.test.webmvc.Person import org.springframework.data.rest.test.webmvc.PersonRepository +import org.springframework.data.rest.test.webmvc.ProfileRepository import org.springframework.data.rest.test.webmvc.TestRepositoryEventListener +import org.springframework.data.rest.webmvc.RepositoryRestConfiguration import org.springframework.data.rest.webmvc.RepositoryRestController import org.springframework.data.rest.webmvc.RepositoryRestMvcConfiguration import org.springframework.http.ResponseEntity @@ -18,7 +20,6 @@ import org.springframework.mock.web.MockHttpServletRequest import org.springframework.orm.jpa.EntityManagerHolder import org.springframework.test.context.ContextConfiguration import org.springframework.transaction.annotation.Transactional -import org.springframework.web.util.UriComponentsBuilder import spock.lang.Specification import javax.persistence.EntityManagerFactory @@ -33,29 +34,25 @@ abstract class BaseSpec extends Specification { @Autowired ApplicationContext appCtx @Autowired TestRepositoryEventListener listener + @Autowired RepositoryRestConfiguration config @Autowired RepositoryRestController controller @Autowired EntityManagerFactory emf @Autowired PersonRepository people @Autowired AddressRepository addresses @Autowired CustomerRepository customers - UriComponentsBuilder baseUri + @Autowired ProfileRepository profiles + URI baseUri def mapper = new ObjectMapper() @Transactional def setup() { - baseUri = UriComponentsBuilder.fromUriString("http://localhost:8080/data") + baseUri = URI.create("http://localhost:8080/data") + config.baseUri = baseUri if (!hasResource(emf)) { bindResource(emf, new EntityManagerHolder(emf.createEntityManager())) } - -// addresses.findAll().each { a -> -// addresses.delete(a) -// } -// people.findAll().each { p -> -// people.delete(p) -// } } def readJson(ResponseEntity entity) { diff --git a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/RelationshipsSpec.groovy b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/RelationshipsSpec.groovy index 5c17a7879..8b2f9cb9b 100644 --- a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/RelationshipsSpec.groovy +++ b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/RelationshipsSpec.groovy @@ -1,8 +1,10 @@ package org.springframework.data.rest.webmvc.spec +import org.springframework.data.rest.test.webmvc.Person +import org.springframework.data.rest.test.webmvc.Profile import org.springframework.http.HttpStatus import org.springframework.transaction.annotation.Transactional -import spock.lang.Ignore +import org.springframework.web.util.UriComponentsBuilder import spock.lang.Shared /** @@ -14,11 +16,18 @@ class RelationshipsSpec extends BaseSpec { Long persId @Shared Long addrId + @Shared + Long profileId def setup() { - def person = newPerson() + def person = people.save(new Person(name: "John Doe")) persId = person.id - addrId = person.addresses[0].id + def addr = newAddress("Uniontown") + addrId = addr.id + def profile = profiles.save(new Profile(type: "socialmedia", url: "http://socialmedia.com", person: person)) + person.profiles = ["socialmedia": profile] + people.save(person) + profileId = profile.id } @Transactional @@ -29,7 +38,7 @@ class RelationshipsSpec extends BaseSpec { "POST", "people/$persId/addresses", null, - [baseUri.pathSegment("address", "$addrId").build().toUriString()] + [UriComponentsBuilder.fromUri(baseUri).pathSegment("address", "$addrId").build().toUriString()] ) when: @@ -44,17 +53,16 @@ class RelationshipsSpec extends BaseSpec { then: response.statusCode == HttpStatus.OK - readJson(response).city == "Univille" + readJson(response).city == "Uniontown" } - @Ignore @Transactional def "cannot delete a required relationship"() { when: - def request = createRequest("DELETE", "address/$addrId/person", null) - def response = controller.clearLinks(request, "address", "$addrId", "person") + def request = createRequest("DELETE", "profile/$profileId/person", null) + def response = controller.clearLinks(request, "profile", "$profileId", "person") then: response.statusCode == HttpStatus.METHOD_NOT_ALLOWED diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Address.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Address.java index 52e07675e..a45aba01b 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Address.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Address.java @@ -1,8 +1,12 @@ package org.springframework.data.rest.test.webmvc; +import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; +import javax.persistence.OneToOne; + +import org.codehaus.jackson.annotate.JsonBackReference; /** * @author Jon Brisbin @@ -15,6 +19,9 @@ public class Address { private String city; private String province; private String postalCode; + @JsonBackReference + @OneToOne(cascade = CascadeType.REMOVE) + private Person person; public Address() { } @@ -62,6 +69,14 @@ public class Address { this.postalCode = postalCode; } + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + @Override public boolean equals(Object o) { if(!(o instanceof Address)) { return false; diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Profile.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Profile.java index 4c620351b..964255605 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Profile.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Profile.java @@ -3,7 +3,7 @@ package org.springframework.data.rest.test.webmvc; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; -import javax.persistence.ManyToOne; +import javax.persistence.OneToOne; import org.codehaus.jackson.annotate.JsonBackReference; @@ -17,7 +17,7 @@ public class Profile { private String type; private String url; @JsonBackReference - @ManyToOne + @OneToOne(optional = false) private Person person; public Profile() { diff --git a/spring-data-rest-webmvc/src/test/resources/META-INF/persistence.xml b/spring-data-rest-webmvc/src/test/resources/META-INF/persistence.xml index 9748b6dde..247d7db3d 100644 --- a/spring-data-rest-webmvc/src/test/resources/META-INF/persistence.xml +++ b/spring-data-rest-webmvc/src/test/resources/META-INF/persistence.xml @@ -2,6 +2,9 @@ org.springframework.data.rest.test.webmvc.Address + org.springframework.data.rest.test.webmvc.Child + org.springframework.data.rest.test.webmvc.Customer + org.springframework.data.rest.test.webmvc.CustomerTracker org.springframework.data.rest.test.webmvc.Family org.springframework.data.rest.test.webmvc.Person org.springframework.data.rest.test.webmvc.Profile diff --git a/spring-data-rest-webmvc/src/test/resources/META-INF/spring-data-rest/repositories-export.xml b/spring-data-rest-webmvc/src/test/resources/META-INF/spring-data-rest/repositories-export.xml index ae52db215..6417d0205 100644 --- a/spring-data-rest-webmvc/src/test/resources/META-INF/spring-data-rest/repositories-export.xml +++ b/spring-data-rest-webmvc/src/test/resources/META-INF/spring-data-rest/repositories-export.xml @@ -8,7 +8,8 @@ + p:jsonpOnErrParamName="errback" + p:baseUri="http://localhost:8080">