DATAREST-233 - Introduced @RepositoryRestResource.
@RepositoryRestResource exposes more detailed attributes tailored to the use case of exposing a repository. @RestResource is still recognized on repository interfaces but we now issue a warning and indicate the new annotation to be used. Introduced a minimal ResourceDescription interface and let @Description be used within @RestResource and @RepositoryRestResource. We now generate default resource bundle keys and resolve them against a "rest-messages" resource bundle by default. JsonSchema converter now uses the rendered descriptions for schema descriptions.
This commit is contained in:
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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.core.domain.jpa;
|
||||
|
||||
import java.util.Date;
|
||||
@@ -7,6 +22,7 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
||||
import org.springframework.data.rest.core.annotation.RestResource;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
@@ -15,8 +31,9 @@ import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
* A repository to manage {@link Person}s.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RestResource(rel = "people", path = "people")
|
||||
@RepositoryRestResource(collectionResourceRel = "people", path = "people")
|
||||
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
|
||||
|
||||
@RestResource(rel = "firstname", path = "firstname")
|
||||
@@ -29,9 +46,9 @@ public interface PersonRepository extends PagingAndSortingRepository<Person, Lon
|
||||
Pageable pageable);
|
||||
|
||||
/**
|
||||
* @see DATAREST-107 - this method matches the earlier one, causing an ambiguous mapping
|
||||
* except for the exported setting
|
||||
* @see DATAREST-107 - this method matches the earlier one, causing an ambiguous mapping except for the exported
|
||||
* setting
|
||||
*/
|
||||
@RestResource(rel = "firstname", path="firstname", exported = false)
|
||||
@RestResource(rel = "firstname", path = "firstname", exported = false)
|
||||
Person findByFirstName(@Param("firstName") String firstName);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2014 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.
|
||||
@@ -17,19 +17,18 @@ package org.springframework.data.rest.core.mapping;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.mongodb.core.mapping.DBRef;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.rest.core.Path;
|
||||
import org.springframework.data.rest.core.annotation.Description;
|
||||
import org.springframework.data.rest.core.annotation.RestResource;
|
||||
import org.springframework.data.rest.core.mapping.ResourceMappings.PersistentPropertyResourceMapping;
|
||||
|
||||
@@ -42,14 +41,6 @@ import org.springframework.data.rest.core.mapping.ResourceMappings.PersistentPro
|
||||
public class PersistentPropertyResourceMappingUnitTests {
|
||||
|
||||
MongoMappingContext mappingContext = new MongoMappingContext();
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(Entity.class);
|
||||
|
||||
@Mock ResourceMapping typeMapping;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
when(typeMapping.isExported()).thenReturn(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-175
|
||||
@@ -57,13 +48,12 @@ public class PersistentPropertyResourceMappingUnitTests {
|
||||
@Test
|
||||
public void usesPropertyNameAsDefaultResourceMappingRelAndPath() {
|
||||
|
||||
MongoPersistentProperty persistentProperty = persistentEntity.getPersistentProperty("first");
|
||||
ResourceMapping propertyMapping = new PersistentPropertyResourceMapping(persistentProperty, typeMapping);
|
||||
ResourceMapping mapping = getPropertyMappingFor(Entity.class, "first");
|
||||
|
||||
assertThat(propertyMapping, is(notNullValue()));
|
||||
assertThat(propertyMapping.getPath(), is(new Path("first")));
|
||||
assertThat(propertyMapping.getRel(), is("first"));
|
||||
assertThat(propertyMapping.isExported(), is(true));
|
||||
assertThat(mapping, is(notNullValue()));
|
||||
assertThat(mapping.getPath(), is(new Path("first")));
|
||||
assertThat(mapping.getRel(), is("first"));
|
||||
assertThat(mapping.isExported(), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,13 +62,12 @@ public class PersistentPropertyResourceMappingUnitTests {
|
||||
@Test
|
||||
public void considersMappingAnnotationOnDomainClassProperty() {
|
||||
|
||||
MongoPersistentProperty persistentProperty = persistentEntity.getPersistentProperty("second");
|
||||
ResourceMapping propertyMapping = new PersistentPropertyResourceMapping(persistentProperty, typeMapping);
|
||||
ResourceMapping mapping = getPropertyMappingFor(Entity.class, "second");
|
||||
|
||||
assertThat(propertyMapping, is(notNullValue()));
|
||||
assertThat(propertyMapping.getPath(), is(new Path("secPath")));
|
||||
assertThat(propertyMapping.getRel(), is("secRel"));
|
||||
assertThat(propertyMapping.isExported(), is(false));
|
||||
assertThat(mapping, is(notNullValue()));
|
||||
assertThat(mapping.getPath(), is(new Path("secPath")));
|
||||
assertThat(mapping.getRel(), is("secRel"));
|
||||
assertThat(mapping.isExported(), is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,29 +76,67 @@ public class PersistentPropertyResourceMappingUnitTests {
|
||||
@Test
|
||||
public void considersMappingAnnotationOnDomainClassPropertyMethod() {
|
||||
|
||||
MongoPersistentProperty persistentProperty = persistentEntity.getPersistentProperty("third");
|
||||
ResourceMapping propertyMapping = new PersistentPropertyResourceMapping(persistentProperty, typeMapping);
|
||||
ResourceMapping mapping = getPropertyMappingFor(Entity.class, "third");
|
||||
|
||||
assertThat(propertyMapping, is(notNullValue()));
|
||||
assertThat(propertyMapping.getPath(), is(new Path("thirdPath")));
|
||||
assertThat(propertyMapping.getRel(), is("thirdRel"));
|
||||
assertThat(propertyMapping.isExported(), is(false));
|
||||
assertThat(mapping, is(notNullValue()));
|
||||
assertThat(mapping.getPath(), is(new Path("thirdPath")));
|
||||
assertThat(mapping.getRel(), is("thirdRel"));
|
||||
assertThat(mapping.isExported(), is(false));
|
||||
}
|
||||
|
||||
static class Entity {
|
||||
@Test
|
||||
public void returnsDefaultDescriptionKey() {
|
||||
|
||||
Related first, third;
|
||||
ResourceMapping mapping = getPropertyMappingFor(Entity.class, "second");
|
||||
|
||||
ResourceDescription description = mapping.getDescription();
|
||||
|
||||
assertThat(description.isDefault(), is(true));
|
||||
assertThat(description.getMessage(), is("rest.description.entity.second"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-???
|
||||
*/
|
||||
@Test
|
||||
public void considersAtDescription() {
|
||||
|
||||
ResourceMapping mapping = getPropertyMappingFor(Entity.class, "fourth");
|
||||
|
||||
ResourceDescription description = mapping.getDescription();
|
||||
assertThat(description.isDefault(), is(false));
|
||||
assertThat(description.getMessage(), is("Some description"));
|
||||
}
|
||||
|
||||
private ResourceMapping getPropertyMappingFor(Class<?> entity, String propertyName) {
|
||||
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entity);
|
||||
MongoPersistentProperty property = persistentEntity.getPersistentProperty(propertyName);
|
||||
|
||||
CollectionResourceMapping entityResourceMapping = new TypeBasedCollectionResourceMapping(entity);
|
||||
ResourceMapping propertyTypeMapping = new TypeBasedCollectionResourceMapping(property.getType());
|
||||
|
||||
return new PersistentPropertyResourceMapping(property, propertyTypeMapping, entityResourceMapping);
|
||||
}
|
||||
|
||||
public static class Entity {
|
||||
|
||||
Related first;
|
||||
@DBRef Related third;
|
||||
|
||||
@DBRef//
|
||||
@RestResource(path = "secPath", rel = "secRel", exported = false)//
|
||||
List<Related> second;
|
||||
|
||||
@Description("Some description") String fourth;
|
||||
|
||||
@RestResource(path = "thirdPath", rel = "thirdRel", exported = false)
|
||||
public Related getThird() {
|
||||
return third;
|
||||
}
|
||||
}
|
||||
|
||||
static class Related {
|
||||
public static class Related {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
|
||||
import org.springframework.data.rest.core.Path;
|
||||
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
||||
import org.springframework.data.rest.core.annotation.RestResource;
|
||||
|
||||
/**
|
||||
@@ -41,7 +42,7 @@ public class RepositoryCollectionResourceMappingUnitTests {
|
||||
|
||||
assertThat(mapping.getPath(), is(new Path("persons")));
|
||||
assertThat(mapping.getRel(), is("persons"));
|
||||
assertThat(mapping.getSingleResourceRel(), is("person"));
|
||||
assertThat(mapping.getItemResourceRel(), is("person"));
|
||||
assertThat(mapping.isExported(), is(true));
|
||||
}
|
||||
|
||||
@@ -52,7 +53,7 @@ public class RepositoryCollectionResourceMappingUnitTests {
|
||||
|
||||
assertThat(mapping.getPath(), is(new Path("bar")));
|
||||
assertThat(mapping.getRel(), is("foo"));
|
||||
assertThat(mapping.getSingleResourceRel(), is("annotatedPerson"));
|
||||
assertThat(mapping.getItemResourceRel(), is("annotatedPerson"));
|
||||
assertThat(mapping.isExported(), is(false));
|
||||
}
|
||||
|
||||
@@ -63,7 +64,7 @@ public class RepositoryCollectionResourceMappingUnitTests {
|
||||
|
||||
assertThat(mapping.getPath(), is(new Path("/trumpsAll")));
|
||||
assertThat(mapping.getRel(), is("foo"));
|
||||
assertThat(mapping.getSingleResourceRel(), is("annotatedPerson"));
|
||||
assertThat(mapping.getItemResourceRel(), is("annotatedPerson"));
|
||||
assertThat(mapping.isExported(), is(true));
|
||||
}
|
||||
|
||||
@@ -82,6 +83,14 @@ public class RepositoryCollectionResourceMappingUnitTests {
|
||||
assertThat(getResourceMappingFor(PersonRepository.class).isPagingResource(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoversCustomizationsUsingRestRepositoryResource() {
|
||||
|
||||
CollectionResourceMapping mapping = getResourceMappingFor(RepositoryAnnotatedRepository.class);
|
||||
assertThat(mapping.getRel(), is("foo"));
|
||||
assertThat(mapping.getItemResourceRel(), is("bar"));
|
||||
}
|
||||
|
||||
private static CollectionResourceMapping getResourceMappingFor(Class<?> repositoryInterface) {
|
||||
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(repositoryInterface);
|
||||
@@ -106,4 +115,7 @@ public class RepositoryCollectionResourceMappingUnitTests {
|
||||
public static class PublicClass {}
|
||||
|
||||
interface PackageProtectedRepository extends Repository<PublicClass, Long> {}
|
||||
|
||||
@RepositoryRestResource(collectionResourceRel = "foo", itemResourceRel = "bar")
|
||||
interface RepositoryAnnotatedRepository extends Repository<Person, Long> {}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = JpaRepositoryConfig.class)
|
||||
@Transactional
|
||||
public class ResourceMappingsIntegrationTest {
|
||||
public class ResourceMappingsIntegrationTests {
|
||||
|
||||
@Autowired ListableBeanFactory factory;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2014 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.
|
||||
@@ -21,15 +21,13 @@ import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.rest.core.Path;
|
||||
import org.springframework.data.rest.core.annotation.RestResource;
|
||||
import org.springframework.data.rest.core.mapping.CollectionResourceMapping;
|
||||
import org.springframework.data.rest.core.mapping.TypeBasedCollectionResourceMapping;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link TypeBasedCollectionResourceMapping}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class TypeBasedCollectionResourceMappingUnitTest {
|
||||
public class TypeBasedCollectionResourceMappingUnitTests {
|
||||
|
||||
@Test
|
||||
public void defaultsMappingsByType() {
|
||||
@@ -38,7 +36,7 @@ public class TypeBasedCollectionResourceMappingUnitTest {
|
||||
|
||||
assertThat(mapping.getPath(), is(new Path("sample")));
|
||||
assertThat(mapping.getRel(), is("samples"));
|
||||
assertThat(mapping.getSingleResourceRel(), is("sample"));
|
||||
assertThat(mapping.getItemResourceRel(), is("sample"));
|
||||
assertThat(mapping.isExported(), is(true));
|
||||
}
|
||||
|
||||
@@ -49,7 +47,7 @@ public class TypeBasedCollectionResourceMappingUnitTest {
|
||||
|
||||
assertThat(mapping.getPath(), is(new Path("customizedSample")));
|
||||
assertThat(mapping.getRel(), is("myRel"));
|
||||
assertThat(mapping.getSingleResourceRel(), is("customizedSample"));
|
||||
assertThat(mapping.getItemResourceRel(), is("customizedSample"));
|
||||
assertThat(mapping.isExported(), is(true));
|
||||
}
|
||||
|
||||
@@ -64,6 +62,24 @@ public class TypeBasedCollectionResourceMappingUnitTest {
|
||||
assertThat(mapping.isExported(), is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see
|
||||
*/
|
||||
@Test
|
||||
public void usesDefaultDescriptionIfNoAnnotationPresent() {
|
||||
|
||||
CollectionResourceMapping mapping = new TypeBasedCollectionResourceMapping(Sample.class);
|
||||
ResourceDescription description = mapping.getDescription();
|
||||
|
||||
assertThat(description.isDefault(), is(true));
|
||||
assertThat(description.getMessage(), is("rest.description.samples"));
|
||||
|
||||
ResourceDescription itemDescription = mapping.getItemResourceDescription();
|
||||
|
||||
assertThat(itemDescription.isDefault(), is(true));
|
||||
assertThat(itemDescription.getMessage(), is("rest.description.sample"));
|
||||
}
|
||||
|
||||
public interface Sample {}
|
||||
|
||||
interface HiddenSample {}
|
||||
@@ -7,7 +7,7 @@
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.data" level="error" />
|
||||
<logger name="org.springframework.data" level="warn" />
|
||||
|
||||
<root level="error">
|
||||
<appender-ref ref="console" />
|
||||
|
||||
Reference in New Issue
Block a user