DATAREST-463 - Hide ignored attributes from ALPS metadata.
If @JsonIgnore is applied to either a field or a getter method for an association, then do not expose that property's metadata down from ALPS. Original pull request: #160.
This commit is contained in:
committed by
Oliver Gierke
parent
67e368e3c7
commit
180d0ce3f4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2015 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.
|
||||
@@ -71,6 +71,7 @@ import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
|
||||
* Converter to create Alps {@link Descriptor} instances for a {@link RootResourceInformation}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
public class RootResourceInformationToAlpsDescriptorConverter {
|
||||
|
||||
@@ -302,7 +303,7 @@ public class RootResourceInformationToAlpsDescriptorConverter {
|
||||
|
||||
private List<Descriptor> buildPropertyDescriptors(Class<?> type, final String baseRel) {
|
||||
|
||||
PersistentEntity<?, ?> entity = persistentEntities.getPersistentEntity(type);
|
||||
final PersistentEntity<?, ?> entity = persistentEntities.getPersistentEntity(type);
|
||||
final List<Descriptor> propertyDescriptors = new ArrayList<Descriptor>();
|
||||
final JacksonMetadata jackson = new JacksonMetadata(mapper, type);
|
||||
final PropertyMappings propertyMappings = new PropertyMappings(mappings);
|
||||
@@ -333,30 +334,28 @@ public class RootResourceInformationToAlpsDescriptorConverter {
|
||||
public void doWithAssociation(Association<? extends PersistentProperty<?>> association) {
|
||||
|
||||
PersistentProperty<?> property = association.getInverse();
|
||||
final Class<?> propertyType = property.getType();
|
||||
|
||||
if (!jackson.isExportableProperty(property)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!associationLinks.isLinkableAssociation(property)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ResourceMapping mapping = propertyMappings.getMappingFor(property);
|
||||
|
||||
DescriptorBuilder builder = descriptor().//
|
||||
name(mapping.getRel()).doc(getDocFor(mapping.getDescription()));
|
||||
|
||||
if (associationLinks.isLinkableAssociation(property)) {
|
||||
ResourceMetadata targetTypeMapping = mappings.getMappingFor(property.getActualType());
|
||||
String localPath = targetTypeMapping.getRel().concat("#").concat(targetTypeMapping.getItemResourceRel());
|
||||
Link link = ControllerLinkBuilder.linkTo(AlpsController.class).slash(localPath).withSelfRel();
|
||||
|
||||
ResourceMetadata targetTypeMapping = mappings.getMappingFor(property.getActualType());
|
||||
String localPath = targetTypeMapping.getRel().concat("#").concat(targetTypeMapping.getItemResourceRel());
|
||||
Link link = ControllerLinkBuilder.linkTo(AlpsController.class).slash(localPath).withSelfRel();
|
||||
|
||||
builder.//
|
||||
type(Type.SAFE).//
|
||||
rt(link.getHref());
|
||||
|
||||
} else {
|
||||
|
||||
List<Descriptor> nestedDescriptors = buildPropertyDescriptors(property.getActualType(), baseRel.concat(".")
|
||||
.concat(mapping.getRel()));
|
||||
|
||||
builder = builder.//
|
||||
type(Type.SEMANTIC).//
|
||||
descriptors(nestedDescriptors);
|
||||
}
|
||||
builder.//
|
||||
type(Type.SAFE).//
|
||||
rt(link.getHref());
|
||||
|
||||
propertyDescriptors.add(builder.build());
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
|
||||
* Value object to abstract Jackson based bean metadata of a given type.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
public class JacksonMetadata implements Iterable<BeanPropertyDefinition> {
|
||||
|
||||
@@ -74,6 +75,15 @@ public class JacksonMetadata implements Iterable<BeanPropertyDefinition> {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given property for a type is avaiaable to be exported, i.e. serialized via Jackson
|
||||
* @param property
|
||||
* @return
|
||||
*/
|
||||
public boolean isExportableProperty(PersistentProperty<?> property) {
|
||||
return getDefinitionFor(property) != null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Iterable#iterator()
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.util.Assert;
|
||||
* A value object to for {@link Link}s representing an association.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Greg Turnquist
|
||||
* @since 2.1
|
||||
*/
|
||||
public class AssociationLinks {
|
||||
@@ -90,6 +91,7 @@ public class AssociationLinks {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ResourceMetadata metadata = mappings.getMappingFor(property.getActualType());
|
||||
ResourceMetadata metadata = mappings.getMappingFor(property.getOwner().getType());
|
||||
|
||||
if (metadata != null && !metadata.isExported(property)) {
|
||||
@@ -99,4 +101,5 @@ public class AssociationLinks {
|
||||
metadata = mappings.getMappingFor(property.getActualType());
|
||||
return metadata == null ? false : metadata.isExported();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2015 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.
|
||||
@@ -32,6 +32,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
* Integration tests for {@link RepositoryController}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
@ContextConfiguration(classes = JpaRepositoryConfig.class)
|
||||
@Transactional
|
||||
@@ -57,17 +58,21 @@ public class RepositoryControllerIntegrationTests extends AbstractControllerInte
|
||||
assertThat(controller.headForRepositories().getStatusCode(), is(HttpStatus.NO_CONTENT));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-160, DATAREST-333, DATAREST-463
|
||||
*/
|
||||
@Test
|
||||
public void exposesLinksToRepositories() {
|
||||
|
||||
RepositoryLinksResource resource = controller.listRepositories().getBody();
|
||||
|
||||
assertThat(resource.getLinks(), hasSize(5));
|
||||
assertThat(resource.getLinks(), hasSize(6));
|
||||
|
||||
assertThat(resource.hasLink("people"), is(true));
|
||||
assertThat(resource.hasLink("orders"), is(true));
|
||||
assertThat(resource.hasLink("addresses"), is(true));
|
||||
assertThat(resource.hasLink("books"), is(true));
|
||||
assertThat(resource.hasLink("authors"), is(true));
|
||||
assertThat(resource.hasLink("items"), is(true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2015 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.
|
||||
@@ -44,6 +44,7 @@ import org.springframework.web.context.WebApplicationContext;
|
||||
* Integration tests for {@link AlpsController}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration(classes = { JpaRepositoryConfig.class, AlpsControllerIntegrationTests.Config.class })
|
||||
@@ -90,6 +91,7 @@ public class AlpsControllerIntegrationTests extends AbstractControllerIntegratio
|
||||
|
||||
assertThat(discoverUnique(profileLink.getHref(), "orders"), is(notNullValue()));
|
||||
assertThat(discoverUnique(profileLink.getHref(), "people"), is(notNullValue()));
|
||||
assertThat(discoverUnique(profileLink.getHref(), "items"), is(notNullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,6 +109,26 @@ public class AlpsControllerIntegrationTests extends AbstractControllerIntegratio
|
||||
andExpect(jsonPath("$.descriptors[*].name", hasItems("people", "person")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAREST-463
|
||||
*/
|
||||
@Test
|
||||
public void verifyThatAttributesIgnoredDontAppearInAlps() throws Exception {
|
||||
|
||||
Link profileLink = discoverUnique("/", "profile");
|
||||
Link usersLink = discoverUnique(profileLink.getHref(), "users");
|
||||
Link itemsLink = discoverUnique(profileLink.getHref(), "items");
|
||||
|
||||
assertThat(usersLink, is(nullValue()));
|
||||
|
||||
mvc.perform(get(itemsLink.getHref())).//
|
||||
andDo(print()).//
|
||||
andExpect(jsonPath("$.descriptors[*].descriptors[*].name", hasItems("id", "name"))).//
|
||||
andExpect(jsonPath("$.descriptors[*].descriptors[*].name",
|
||||
everyItem(not(isIn(new String[]{"owner", "manager", "curator"})))));
|
||||
|
||||
}
|
||||
|
||||
private Link discoverUnique(String href, String rel) throws Exception {
|
||||
|
||||
MockHttpServletResponse response = mvc.perform(get(href)).//
|
||||
@@ -116,4 +138,5 @@ public class AlpsControllerIntegrationTests extends AbstractControllerIntegratio
|
||||
LinkDiscoverer discoverer = discoverers.getLinkDiscovererFor(MediaType.valueOf(response.getContentType()));
|
||||
return discoverer.findLinkWithRel(rel, response.getContentAsString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2015 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.jpa;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* @author Greg Turnquist
|
||||
* @see DATAREST-463
|
||||
*/
|
||||
@Entity
|
||||
public class Item {
|
||||
|
||||
@Id @GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@JsonIgnore
|
||||
@OneToOne
|
||||
private User owner;
|
||||
|
||||
@OneToOne
|
||||
private User manager;
|
||||
|
||||
@OneToOne
|
||||
private User curator;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public User getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(User owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public User getManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
public void setManager(User manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public User getCurator() {
|
||||
return curator;
|
||||
}
|
||||
|
||||
public void setCurator(User curator) {
|
||||
this.curator = curator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2015 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.jpa;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
/**
|
||||
* @author Greg Turnquist
|
||||
* @see DATAREST-463
|
||||
*/
|
||||
public interface ItemRepository extends CrudRepository<Item, Long> {
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2015 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.jpa;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* @author Greg Turnquist
|
||||
* @see DATAREST-463
|
||||
*/
|
||||
@Entity
|
||||
public class User {
|
||||
|
||||
@Id @GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@JsonIgnore
|
||||
private String password;
|
||||
|
||||
private String[] roles;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String[] getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(String... roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2015 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.jpa;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
||||
|
||||
/**
|
||||
* @author Greg Turnquist
|
||||
* @see DATAREST-463
|
||||
*/
|
||||
@RepositoryRestResource(exported = false)
|
||||
public interface UserRepository extends CrudRepository<User, Long> {
|
||||
}
|
||||
Reference in New Issue
Block a user