We now use the newly introduced IdentifierAccessor API to make sure we benefit from store specific optimizations when looking up identifier values.
Added some user class lookups to make sure the projection and resource mapping lookup works if proxies types are handed around.
We now use the PersistentPropertyAccessor provided by the PersistentEntity to lookup property values to benefit from store-specific customizations. Code that relies on value conversion by using a ConversionService now explicitly uses a ConvertingPropertyAccessor.
Related tickets: DATACMNS-596.
Introduced SupportedHttpMethods abstraction to be able to test the exposure of HTTp methods based on a CrudMethods instance only. Moved ResourceType to the core module.
Decouple the test machinery of this class from the barrage of common test cases used against the various data stores. This way, other test suites that use the same integration approach don't have to be a part of this class hierarchy. Also move utilities and assertion methods into separate utility classes to slim down the class hierarchy.
Original pull request: #149.
Search resources are now considered sortable if they contain a Sort parameter. This is now reflected in MethodResourceMapping.isSortableResource().
Building on top of that, the RepositorySearchController now appends the sort template variable to links generated when listing search resources. It also now accepts resolved Sort instances to forward them to the query method execution. The controller now also uses DefaultedPageable so that request missing pagination information use the defaults configured for the PageableHandlerMethodArgumentResolver.
Removed class-level @RequestMapping annotations as the controllers get picked up by standard Spring MVC and are exposed via the root even if a base URI is configured. Created custom @BaseUriAwareController and use that in AlpsController to make sure it doesn't get picked up by Spring MVC.
We now don't expose the PersistentEntityJackson2Module as bean anymore to prevent global registration in case of a Boot setup. The HttpMessageConverters registered are now TypeConstrainedMappingJackson2HttpMessageConverters so that they only get used of the object to marshal is of type ResourceSupport.
As recommended in RFC 5789, the support for PATCH request should be advertised in OPTIONS requests (already in place) and include an Accept-Patch header listing the patch media types supported. We now include the media types for JSON Patch, JSON Merge Patch and plain JSON in that header.
[0] http://tools.ietf.org/html/rfc5789#section-3
This commit adds the support to expose additional resources that serve ALPS [0] resources to document the available state transitions and representations. The exposure is enabled by default and can be customized using the RepositoryRestConfiguration.metadataConfiguration() object.
Currently the set of descriptors exposed includes:
- A descriptor for the representation of the domain type. Linkable associations are represented as safe descriptors, ones that are not linked are semantic descriptors.
- Descriptors for each supported HTTP method for both the collection and item resources to indicate the ability to update, create, delete etc.
- Safe descriptors (e.g. to access the collection or item resource) get potentially available customizations (pagination, projections) attached through nested descriptors.
Documentation
An ALPS descriptor contains a doc attribute to carry semantic information for the end user or a potential client to display. The information can be described in two ways: the first one is the @Description annotation that captures the plain text information one wants to get listed. It is supported in @RepositoryRestResource, on query methods, projection interfaces and accessors etc.
The preferred approach however is to use a resource bundle rest-messages.properties. For each descriptor we will resolve a key starting with rest.description followed by a dot path into the resource. By default, doc attributes are only rendered if the resource bundle contains an entry for the relevant key. You can enforce displaying unresolved keys by configuring MetadataConfiguration.omitUnresolvableDescriptionKeys(…).
For representation descriptors and and the parameter list of query method descriptors we will display enum values by default as comma-separated list. The list is also available as message resolution argument, so that you can refer to the list in your description message via the {0} placeholder.
TODOs:
- Improve descriptors for associations (indicate ability to update etc.)
[0] ALPS - http://alps.io
We now support PATCH request with application/json-patch+json [0] and application/merge-patch+json media types. The support is based on some customized usage of the FGE JSON Patch library [2].
As we need to apply the patch to an existing object, we need translate the JSON Patch remove operation into a replace operation setting the value to null so that out entity processing component registers the request for removal. Same applies to requests for merge-patch+json.
From an implementation point of view the handling of the media type has moved from the controller into PersistentEntityResourceHandlerMethodArgumentResolver and its delegates, n particular JsonPatchHandler. The application of the changes to the existing domain object is handled in the newly introduced DomainObjectReader.
Related ticket: DATAREST-345.
[0] http://tools.ietf.org/html/rfc6902
[1] http://tools.ietf.org/html/draft-ietf-appsawg-json-merge-patch
[2] https://github.com/fge/json-patch
Added explicit dependency to jackson-annotations as a library previously declared might pull in that one in a different version which might cause conflicts.
AssociationOmittingSerializerModifier previously dropped the writer fro a particular property if it couldn't find a PersistentProperty for the bean property. We now keep those writers to make sure that non-persistent, additional fields are written as well.
Related issues: https://github.com/spring-projects/spring-boot/issues/1190
Previously, if a persistent property was renamed using e.g. @JsonProperty, the lookup of the PersistentProperty failed as BeanPropertyWriter exposes the final (renamed) property name, not the internal one. We now defensively lookup the correct BeanPropertyDescriptor using the external name and use the corresponding internal one for the PersistentProperty lookup.
During type matching in ResourcesProcessorWrapper we now accomodate the scenario that a Resources type is completely different than the Resources type to look for. This resulted in null being returned for the supertype generics lookup and this failed as the corresponding guard was missing.
The root resource, collection and item resources as well as the search and query method resources now expose a handler method to handle OPTIONS requests and return a response with the Allow header set to the HTTP methods appropriate to the resource requested.
Added some additional methods for HEAD requests and a few integration tests for functionality that previously existed.
Related ticket: DATAREST-330.
Removed the wirings for PlatformTransactionManager and ValidationExceptionHandler from AbstractRepositoryRestController. Removed the latter entirely as it doesn't seem to be used anywhere anyway.
ResourceProcessorHandlerMethodReturnValueHandler now also invokes ResourceProcessors that are typed to Resources even if the value returned by the controller is a sub-type of it.
Also added test cases for the invocation of processors for projections.
The bean definition for annotatedHandlerBeanPostProcessor now is a static one so that it doesn't require the config class to be instantiated and populated, which caused the (too) eager initialization of all dependent beans.
Also we now leniently lookup all ResourceProcessor instances available in the context to prevent the lookup during config class preparation.
Ignore Neo4j tests now as they run into OutOfMemoryErrors.
This commit adds a mechanism to define excerpt projections to be rendered for exposed repositories. The main user facing mechanism is the addition of the excerptProjection attribute to @RepositoryRestResource. This attribute takes a type which has to be a projection interface (see DATAREST-221 for more information about the general mechanism).
If such a excerpt projection is in place, it will be used by default when rendering instances of the domain type in _embedded clauses or if it is related to.
class Person {
String name;
int age;
Person father;
Person mother;
Set<Person> siblings:
}
interface PersonExcerpt {
String getName();
}
If PersonExcerpt is now configured as excerpt projection for Person the collection resource for people will return:
{ _embedded : {
people : [{
name : "Some name",
_embedded : {
mother : { name : "…" },
father : { name : "…" },
siblings : [ … ]
},
_links : { self : { href : "…" }}
}, … ]
}
}
Here you can see how the age property is omitted when rendering a person in a collection. Also each person contains the excerpt projections of related resources and the links to them omitted. If you now follow the link to the item resource, you'll something like this:
{ name : "Some name",
age : 34,
_embedded : {
mother : { name : "…" },
father : { name : "…" },
siblings : [ … ]
},
_links : {
self : { href : "…" },
mother : { href : "…" },
father : { href : "…" },
siblings : { href : "…" }
}
}
Note, that age appears, as the representation is now rendered entirely. We also see the excerpts of related resource but also the links pointing to them in case you want to manage them.
We now defensively guard against URI templates submitted for related resources and expand the incoming URI string source to avoid URI.create(…) to fail.
Also, RepositoryPropertyReferenceController.loadPropertyValue(…) now also uses UriTemplate to guard against Uri templates provided for property references.
Fixed the request parameter binding of RepositorySearchController. executeSearchCompact(…). Changed returned value to Resources to be able to use the EMPTY_RESOURCES_LIST constant to indicate no actual results.
Original pull request: #139.
BaseUri now strips away the tail of a lookup path starting with {. An unencoded { must never appear in a URI but could accidentally be sent by a client forgetting to expand URI templates we return.
We need to proactively strip trailing slashes during base URI handling as even on a successful match (which previously left trailing slashes intact) this might subsequently on the resolving of the repository metadata when evaluating the left-over lookup path against the @RequestMapping methods (which keeps trailing slashes).
We now strip trailing and leading slashes from configured base URI to make sure the matching algorithm accommodates both lookup paths with and without trailing slashes.
Added a few more tests in shape of unit tests for BaseUri.
Introduced BaseUri value object being able to extract the lookup path within the Spring Data REST URI namespace from requests and plain lookup paths. This encapsulates the logic we previously had in RepositoryRestHandlerMapping but it is needed in the HandlerMethodArgumentResolver implementations as well to make sure they extract RepositoryMetadata correctly.
Refined the algorithm to detect the lookup path within the configured base URI, even if the base URI was defined in an absolute way. Also, solidified the implementation against URIs with trailing slashes.
RepositorRestConfiguration now has a ….useHalAsDefaultJsonMediaType() which defaults to true. Configuring this to false allows to still use HAL as default media type in case no Accept header is set or it is set to */*. The flag decides what to return when an Accept header is set to application/json.
In case a base URI is an absolute one, we now rely on only the base URI as foundation for all links created. Relative base URIs are considered are considered an amendment to the current server base up until the servlet mapping. The latter allows to create a dedicated URI namespace for Spring Data REST exposed resources.
Major overhaul of mapping detection in RepositoryRestHandlerMapping. We now correctly map URIs if a base URI is configured via RepositoryRestConfiguration.