Changed the way baseUri is calculated. Changed tests to accommodate new method signatures, fix failing tests.

* Added a configuration property to `RepositoryRestConfiguration` for deployments behind a proxy which do not know the external URL to use as the baseUri for links.
* Changed the way the baseUri is injected into the controller by introducing a `BaseUriMethodArgumentResolver` to inject the proper baseUri (either the one from the configuration, or the one from the request if that's not specified).
This commit is contained in:
Jon Brisbin
2012-10-01 09:52:46 -05:00
committed by Jon Brisbin
parent 697f39d5b0
commit df3b60ba41
15 changed files with 169 additions and 96 deletions

View File

@@ -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();
}
}

View File

@@ -26,10 +26,13 @@ import org.springframework.util.Assert;
*/
public class EntityToResourceConverter implements Converter<Object, Resource> {
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<Object, Resource> {
return new Resource<Object>(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<Link> links = new HashSet<Link>();
for(Object attrName : entityMetadata.linkedAttributes().keySet()) {

View File

@@ -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);
}
}

View File

@@ -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.
*

View File

@@ -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<URI> BASE_URI = new ThreadLocal<URI>();
public static final String LOCATION = "Location";
public static final String SELF = "self";
//public static final ThreadLocal<URI> BASE_URI = new ThreadLocal<URI>();
private static final Logger LOG = LoggerFactory.getLogger(
RepositoryRestController.class);
@@ -332,7 +332,7 @@ public class RepositoryRestController
for(String repoName : (Set<String>)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<Link> links = new ArrayList<Link>();
for(RepositoryExporter repoExporter : repositoryExporters) {
for(String name : (Set<String>)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<Link> links = new HashSet<Link>();
@@ -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 <pre>returnBody=true</pre>.
*
* @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);
}

View File

@@ -20,6 +20,7 @@ public class RepositoryRestHandlerAdapter extends ResourceProcessorInvokingHandl
public RepositoryRestHandlerAdapter(RepositoryRestConfiguration config) {
setCustomArgumentResolvers(Arrays.asList(
new ServerHttpRequestMethodArgumentResolver(),
new BaseUriMethodArgumentResolver(config),
new PagingAndSortingMethodArgumentResolver(config)
));
}

View File

@@ -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<JsonSchemaCo
)
@ResponseBody
public ResponseEntity<?> 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.");

View File

@@ -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<RepositoryExporter> 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 {

View File

@@ -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) {

View File

@@ -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

View File

@@ -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 <jbrisbin@vmware.com>
@@ -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;

View File

@@ -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() {

View File

@@ -2,6 +2,9 @@
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="jpa.sample">
<class>org.springframework.data.rest.test.webmvc.Address</class>
<class>org.springframework.data.rest.test.webmvc.Child</class>
<class>org.springframework.data.rest.test.webmvc.Customer</class>
<class>org.springframework.data.rest.test.webmvc.CustomerTracker</class>
<class>org.springframework.data.rest.test.webmvc.Family</class>
<class>org.springframework.data.rest.test.webmvc.Person</class>
<class>org.springframework.data.rest.test.webmvc.Profile</class>

View File

@@ -8,7 +8,8 @@
<bean id="config" class="org.springframework.data.rest.webmvc.RepositoryRestConfiguration"
p:jsonpParamName="callback"
p:jsonpOnErrParamName="errback">
p:jsonpOnErrParamName="errback"
p:baseUri="http://localhost:8080">
<property name="domainTypeToRepositoryMappings">
<map key-type="java.lang.Class" value-type="java.lang.Class">
<entry key="org.springframework.data.rest.test.webmvc.Person"

View File

@@ -9,7 +9,7 @@ curl -v -d "http://localhost:8080/address/1" -H "Content-Type: text/uri-list" ht
curl -v -d "http://localhost:8080/people/1" -X PUT -H "Content-Type: text/uri-list" http://localhost:8080/address/1/person
curl -v -d '{"postalCode":"54321","province":"MO","lines":["2 W 1st St."],"city":"Univille","person": {"href":"http://localhost:8080/people/2"}}' -H "Content-Type: application/json" http://localhost:8080/address
curl -v -d "http://localhost:8080/address/2" -H "Content-Type: text/uri-list" http://localhost:8080/people/2/addresses
curl -v -d '{"type" : "twitter", "url": "#!/johndoe"}' -H "Content-Type: application/json" http://localhost:8080/profile
curl -v -d "http://localhost:8080/profile/1" -H "Content-Type: text/uri-list" http://localhost:8080/people/1/profiles
curl -v -d '{"type" : "facebook", "url": "/janedoe"}' -H "Content-Type: application/json" http://localhost:8080/profile
curl -v -d '{"links": [{"rel":"facebook", "href": "http://localhost:8080/profile/2"}]}' -H "Content-Type: application/json" http://localhost:8080/people/2/profiles
curl -v -d '{"type" : "twitter", "url": "#!/johndoe", "person": {"href": "http://localhost:8080/people/1"}}' -H "Content-Type: application/json" http://localhost:8080/profile
#curl -v -d "http://localhost:8080/profile/1" -H "Content-Type: text/uri-list" http://localhost:8080/people/1/profiles
curl -v -d '{"type" : "facebook", "url": "/janedoe", "person": {"href": "http://localhost:8080/people/2"}}' -H "Content-Type: application/json" http://localhost:8080/profile
#curl -v -d '{"links": [{"rel":"facebook", "href": "http://localhost:8080/profile/2"}]}' -H "Content-Type: application/json" http://localhost:8080/people/2/profiles