From f8c7a1c376f64b9a36f5bb6bf834458402fd8b09 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Mon, 6 Jul 2015 17:17:15 +0200 Subject: [PATCH] DATAREST-609 - Removed server-side template expansion for incoming URI mapping. Previously we leniently expanded incoming URIs prior to mapping them to controllers. As the original ticket describes, this can cause security issues in rather lenient security setups as the call might bypass a simple security rule but then eventually map to a URI mapped to a stricter security rule. Made sure that self links now return canonical URIs instead of templates. To still advertise projections, PersistentEntityResourceAssembler now adds an additional link to the canonical resource to resources that contains the unexpanded template. Switched from requiring a Repositories instance to PersistentEntities on the way. Related tickets: DATAREST-267, DATAREST-268, DATAREST-300, DATAREST-318, SEC-3027. --- .../data/rest/webmvc/BaseUri.java | 3 +- .../PersistentEntityResourceAssembler.java | 34 +++++---- ...tityResourceAssemblerArgumentResolver.java | 13 ++-- .../RepositoryRestMvcConfiguration.java | 19 ++--- .../AbstractControllerIntegrationTests.java | 4 +- .../data/rest/webmvc/BaseUriUnitTests.java | 26 +------ ...tityResourceAssemblerIntegrationTests.java | 73 +++++++++++++++++++ ...RepositoryRestHandlerMappingUnitTests.java | 13 ++++ .../data/rest/webmvc/mongodb/UserSummary.java | 29 ++++++++ ...ethodArgumentResolverIntegrationTests.java | 20 +---- 10 files changed, 158 insertions(+), 76 deletions(-) create mode 100644 spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/PersistentEntityResourceAssemblerIntegrationTests.java create mode 100644 spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mongodb/UserSummary.java diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BaseUri.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BaseUri.java index 8bce1fc59..f1cc177cc 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BaseUri.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BaseUri.java @@ -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. @@ -111,7 +111,6 @@ public class BaseUri { Assert.notNull(lookupPath, "Lookup path must not be null!"); - lookupPath = lookupPath.contains("{") ? lookupPath.substring(0, lookupPath.indexOf('{')) : lookupPath; lookupPath = trimTrailingCharacter(lookupPath, '/'); if (!baseUri.isAbsolute()) { diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResourceAssembler.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResourceAssembler.java index b5892e951..9a705a9c4 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResourceAssembler.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PersistentEntityResourceAssembler.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-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. @@ -24,7 +24,7 @@ import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.mapping.PersistentPropertyAccessor; import org.springframework.data.mapping.SimpleAssociationHandler; -import org.springframework.data.repository.support.Repositories; +import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.data.rest.core.mapping.ResourceMappings; import org.springframework.data.rest.core.mapping.ResourceMetadata; import org.springframework.data.rest.webmvc.PersistentEntityResource.Builder; @@ -44,7 +44,7 @@ import org.springframework.util.Assert; */ public class PersistentEntityResourceAssembler implements ResourceAssembler { - private final Repositories repositories; + private final PersistentEntities entities; private final EntityLinks entityLinks; private final Projector projector; private final ResourceMappings mappings; @@ -53,20 +53,20 @@ public class PersistentEntityResourceAssembler implements ResourceAssembler entity = repositories.getPersistentEntity(source.getClass()); + PersistentEntity entity = entities.getPersistentEntity(source.getClass()); return PersistentEntityResource.build(instance, entity).// withEmbedded(getEmbeddedResources(source)).// - withLink(getSelfLinkFor(source)); + withLink(getSelfLinkFor(source)).// + withLink(getSingleResourceLinkTo(source)); } /** @@ -115,7 +116,7 @@ public class PersistentEntityResourceAssembler implements ResourceAssembler entity = repositories.getPersistentEntity(instance.getClass()); + PersistentEntity entity = entities.getPersistentEntity(instance.getClass()); final List associationProjections = new ArrayList(); final PersistentPropertyAccessor accessor = entity.getPropertyAccessor(instance); @@ -183,20 +184,23 @@ public class PersistentEntityResourceAssembler implements ResourceAssembler instanceType = instance.getClass(); - PersistentEntity entity = repositories.getPersistentEntity(instanceType); + PersistentEntity entity = entities.getPersistentEntity(instanceType); if (entity == null) { - throw new IllegalArgumentException(String.format("Cannot create self link for %s! No persistent entity found!", - instanceType)); + throw new IllegalArgumentException( + String.format("Cannot create self link for %s! No persistent entity found!", instanceType)); } Object id = entity.getIdentifierAccessor(instance).getIdentifier(); - Link resourceLink = entityLinks.linkToSingleResource(entity.getType(), id); - return new Link(resourceLink.getHref(), Link.REL_SELF); + return entityLinks.linkToSingleResource(entity.getType(), id); } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceAssemblerArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceAssemblerArgumentResolver.java index 4dfe880e7..d5ef70b66 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceAssemblerArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/PersistentEntityResourceAssemblerArgumentResolver.java @@ -16,6 +16,7 @@ package org.springframework.data.rest.webmvc.config; import org.springframework.core.MethodParameter; +import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.data.projection.ProjectionFactory; import org.springframework.data.repository.support.Repositories; import org.springframework.data.rest.core.mapping.ResourceMappings; @@ -36,7 +37,7 @@ import org.springframework.web.method.support.ModelAndViewContainer; */ public class PersistentEntityResourceAssemblerArgumentResolver implements HandlerMethodArgumentResolver { - private final Repositories repositories; + private final PersistentEntities entities; private final EntityLinks entityLinks; private final ProjectionDefinitions projectionDefinitions; private final ProjectionFactory projectionFactory; @@ -46,20 +47,20 @@ public class PersistentEntityResourceAssemblerArgumentResolver implements Handle * Creates a new {@link PersistentEntityResourceAssemblerArgumentResolver} for the given {@link Repositories}, * {@link EntityLinks}, {@link ProjectionDefinitions} and {@link ProjectionFactory}. * - * @param repositories must not be {@literal null}. + * @param entities must not be {@literal null}. * @param entityLinks must not be {@literal null}. * @param projectionDefinitions must not be {@literal null}. * @param projectionFactory must not be {@literal null}. */ - public PersistentEntityResourceAssemblerArgumentResolver(Repositories repositories, EntityLinks entityLinks, + public PersistentEntityResourceAssemblerArgumentResolver(PersistentEntities entities, EntityLinks entityLinks, ProjectionDefinitions projectionDefinitions, ProjectionFactory projectionFactory, ResourceMappings mappings) { - Assert.notNull(repositories, "Repositories must not be null!"); + Assert.notNull(entities, "PersistentEntities must not be null!"); Assert.notNull(entityLinks, "EntityLinks must not be null!"); Assert.notNull(projectionDefinitions, "ProjectionDefinitions must not be null!"); Assert.notNull(projectionFactory, "ProjectionFactory must not be null!"); - this.repositories = repositories; + this.entities = entities; this.entityLinks = entityLinks; this.projectionDefinitions = projectionDefinitions; this.projectionFactory = projectionFactory; @@ -87,6 +88,6 @@ public class PersistentEntityResourceAssemblerArgumentResolver implements Handle PersistentEntityProjector projector = new PersistentEntityProjector(projectionDefinitions, projectionFactory, projectionParameter, mappings); - return new PersistentEntityResourceAssembler(repositories, entityLinks, projector, mappings); + return new PersistentEntityResourceAssembler(entities, entityLinks, projector, mappings); } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java index 9e95e2303..97f24ee1b 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java @@ -141,7 +141,7 @@ import com.fasterxml.jackson.databind.SerializationFeature; @Configuration @EnableHypermediaSupport(type = HypermediaType.HAL) @ComponentScan(basePackageClasses = RepositoryRestController.class, - includeFilters = @Filter(BasePathAwareController.class), useDefaultFilters = false) + includeFilters = @Filter(BasePathAwareController.class) , useDefaultFilters = false) @ImportResource("classpath*:META-INF/spring-data-rest/**/*.xml") @Import(SpringDataJacksonConfiguration.class) public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebConfiguration { @@ -171,8 +171,8 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon List> arrayList = new ArrayList>(); - for (MappingContext context : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, - MappingContext.class).values()) { + for (MappingContext context : BeanFactoryUtils + .beansOfTypeIncludingAncestors(applicationContext, MappingContext.class).values()) { arrayList.add(context); } @@ -406,7 +406,8 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon RestMediaTypes.JSON_PATCH_JSON, RestMediaTypes.MERGE_PATCH_JSON, // RestMediaTypes.SPRING_DATA_VERBOSE_JSON, RestMediaTypes.SPRING_DATA_COMPACT_JSON)); - TypeConstrainedMappingJackson2HttpMessageConverter jacksonConverter = new ResourceSupportHttpMessageConverter(order); + TypeConstrainedMappingJackson2HttpMessageConverter jacksonConverter = new ResourceSupportHttpMessageConverter( + order); jacksonConverter.setObjectMapper(objectMapper()); jacksonConverter.setSupportedMediaTypes(mediaTypes); @@ -578,8 +579,8 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon @Bean public RepositoryInvokerFactory repositoryInvokerFactory() { - return new UnwrappingRepositoryInvokerFactory(new DefaultRepositoryInvokerFactory(repositories(), - defaultConversionService())); + return new UnwrappingRepositoryInvokerFactory( + new DefaultRepositoryInvokerFactory(repositories(), defaultConversionService())); } @Bean @@ -661,7 +662,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon projectionFactory.setResourceLoader(applicationContext); PersistentEntityResourceAssemblerArgumentResolver peraResolver = new PersistentEntityResourceAssemblerArgumentResolver( - repositories(), entityLinks(), config().projectionConfiguration(), projectionFactory, resourceMappings()); + persistentEntities(), entityLinks(), config().projectionConfiguration(), projectionFactory, resourceMappings()); HateoasPageableHandlerMethodArgumentResolver pageableResolver = pageableResolver(); HandlerMethodArgumentResolver defaultedPageableResolver = new DefaultedPageableHandlerMethodArgumentResolver( @@ -669,8 +670,8 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon return Arrays.asList(defaultedPageableResolver, pageableResolver, sortResolver(), serverHttpRequestMethodArgumentResolver(), repoRequestArgumentResolver(), persistentEntityArgumentResolver(), - resourceMetadataHandlerMethodArgumentResolver(), HttpMethodHandlerMethodArgumentResolver.INSTANCE, - peraResolver, backendIdHandlerMethodArgumentResolver(), eTagArgumentResolver()); + resourceMetadataHandlerMethodArgumentResolver(), HttpMethodHandlerMethodArgumentResolver.INSTANCE, peraResolver, + backendIdHandlerMethodArgumentResolver(), eTagArgumentResolver()); } @Autowired GeoModule geoModule; diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AbstractControllerIntegrationTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AbstractControllerIntegrationTests.java index 4edfc313a..82fa80f71 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AbstractControllerIntegrationTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/AbstractControllerIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-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. @@ -53,7 +53,7 @@ public abstract class AbstractControllerIntegrationTests { @Bean public PersistentEntityResourceAssembler persistentEntityResourceAssembler() { - return new PersistentEntityResourceAssembler(repositories(), entityLinks(), StubProjector.INSTANCE, + return new PersistentEntityResourceAssembler(persistentEntities(), entityLinks(), StubProjector.INSTANCE, resourceMappings()); } } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/BaseUriUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/BaseUriUnitTests.java index 7bbae6fe9..a8bbf6416 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/BaseUriUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/BaseUriUnitTests.java @@ -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. @@ -21,8 +21,6 @@ import static org.junit.Assert.*; import java.net.URI; import org.junit.Test; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.context.request.ServletWebRequest; /** * Unit tests for {@link BaseUri}. @@ -89,26 +87,4 @@ public class BaseUriUnitTests { assertThat(uri.getRepositoryLookupPath("/foo/people"), is("/people")); assertThat(uri.getRepositoryLookupPath("/foo/people/"), is("/people")); } - - /** - * @see DATAREST-300 - */ - @Test - public void stripsTemplateVariablesFromPath() { - - BaseUri uri = new BaseUri(URI.create("foo")); - assertThat(uri.getRepositoryLookupPath("/foo/bar{?projection}"), is("/bar")); - } - - /** - * @see DATAREST-318 - */ - @Test - public void stripsTemplateVariablesFromRequest() { - - BaseUri uri = new BaseUri(URI.create("foo")); - - ServletWebRequest request = new ServletWebRequest(new MockHttpServletRequest("GET", "/foo/bar{?projection}")); - assertThat(uri.getRepositoryLookupPath(request), is("/bar")); - } } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/PersistentEntityResourceAssemblerIntegrationTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/PersistentEntityResourceAssemblerIntegrationTests.java new file mode 100644 index 000000000..68a602274 --- /dev/null +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/PersistentEntityResourceAssemblerIntegrationTests.java @@ -0,0 +1,73 @@ +/* + * 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; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + +import java.math.BigInteger; + +import org.hamcrest.Matchers; +import org.junit.Test; +import org.mockito.internal.stubbing.answers.ReturnsArgumentAt; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mapping.context.PersistentEntities; +import org.springframework.data.rest.webmvc.AbstractControllerIntegrationTests.TestConfiguration; +import org.springframework.data.rest.webmvc.mongodb.MongoDbRepositoryConfig; +import org.springframework.data.rest.webmvc.mongodb.User; +import org.springframework.data.rest.webmvc.support.Projector; +import org.springframework.hateoas.EntityLinks; +import org.springframework.hateoas.Link; +import org.springframework.hateoas.Links; +import org.springframework.test.context.ContextConfiguration; + +/** + * Integration tests for {@link PersistentEntityResourceAssembler}. + * + * @author Oliver Gierke + */ +@ContextConfiguration(classes = { TestConfiguration.class, MongoDbRepositoryConfig.class }) +public class PersistentEntityResourceAssemblerIntegrationTests extends AbstractControllerIntegrationTests { + + @Autowired PersistentEntities entities; + @Autowired EntityLinks entityLinks; + + /** + * @see DATAREST-609 + */ + @Test + public void addsSelfAndSingleResourceLinkToResourceByDefault() { + + Projector projector = mock(Projector.class); + + when(projector.projectExcerpt(anyObject())).thenAnswer(new ReturnsArgumentAt(0)); + + PersistentEntityResourceAssembler assembler = new PersistentEntityResourceAssembler(entities, entityLinks, + projector, mappings); + + User user = new User(); + user.id = BigInteger.valueOf(4711); + + Links links = new Links(assembler.toResource(user).getLinks()); + + assertThat(links, is(Matchers. iterableWithSize(2))); + assertThat(links.getLink("self").getVariables(), is(Matchers.empty())); + assertThat(links.getLink("user").getVariableNames(), is(hasItem("projection"))); + } + +} diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMappingUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMappingUnitTests.java index dff1906ff..4b747386d 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMappingUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerMappingUnitTests.java @@ -220,4 +220,17 @@ public class RepositoryRestHandlerMappingUnitTests { assertThat(method, is(nullValue())); } + + /** + * @see DATAREST-609 + */ + @Test + public void rejectsUnexpandedUriTemplateWithNotFound() throws Exception { + + when(mappings.exportsTopLevelResourceFor("/people")).thenReturn(true); + + mockRequest = new MockHttpServletRequest("GET", "/people{?projection}"); + + assertThat(handlerMapping.getHandler(mockRequest), is(nullValue())); + } } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mongodb/UserSummary.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mongodb/UserSummary.java new file mode 100644 index 000000000..6eb6b7cc4 --- /dev/null +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/mongodb/UserSummary.java @@ -0,0 +1,29 @@ +/* + * 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.mongodb; + +import org.springframework.data.rest.core.config.Projection; + +/** + * @author Oliver Gierke + */ +@Projection(types = User.class) +public interface UserSummary { + + String getFirstname(); + + String getLastname(); +} diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/support/BackendIdConverterHandlerMethodArgumentResolverIntegrationTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/support/BackendIdConverterHandlerMethodArgumentResolverIntegrationTests.java index c3f1f126e..d69100e9a 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/support/BackendIdConverterHandlerMethodArgumentResolverIntegrationTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/support/BackendIdConverterHandlerMethodArgumentResolverIntegrationTests.java @@ -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. @@ -39,25 +39,11 @@ import org.springframework.web.context.request.ServletWebRequest; * @author Oliver Gierke */ @ContextConfiguration(classes = JpaRepositoryConfig.class) -public class BackendIdConverterHandlerMethodArgumentResolverIntegrationTests extends AbstractControllerIntegrationTests { +public class BackendIdConverterHandlerMethodArgumentResolverIntegrationTests + extends AbstractControllerIntegrationTests { @Autowired BackendIdHandlerMethodArgumentResolver resolver; - /** - * @see DATAREST-267, DATAREST-268 - */ - @Test - public void stripsUriTemplateVariablesFromUri() throws Exception { - - Method method = ReflectionUtils.findMethod(SampleController.class, "resolveId", Serializable.class); - MethodParameter parameter = new MethodParameter(method, 0); - NativeWebRequest request = new ServletWebRequest(new MockHttpServletRequest("GET", "/orders/5{?projection}")); - - Object resolvedId = resolver.resolveArgument(parameter, null, request, null); - - assertThat(resolvedId, is((Object) "5")); - } - /** * @see DATAREST-155 */