We now expose the constructor that takes a RelProvider in RepositoryResourceMappings so that clients can tweak the default relation names. Changed the order of constructor parameters of (previously) non-public constructors for consistency.
The RelProvider to be used with the mappings can now be configured via RepositoryRestConfiguration and defaults to the EvoInflector based one.
When a PATCH call using JSON Patch tried to append an item to an empty collection, it previously failed to look up the type to unmarshal the incoming payload to. We now inspect the declared types on the wrapped object's property to determine that type for append operations.
Also, an uninitialized collection is now initialized using Spring's CollectionFactory.
Additional cleanups in QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver to make sure a QuerydslRepositoryInvokerAdapter is only applied if the QuerydslPredicateBuilder actually exposes a predicate. Extracted a couple of methods to make sure the mapping pipeline reads nicely.
We now consider the base URI when resolving CORS configuration from repository interfaces. The base URI is now stripped from the request. Previously the base URI was not stripped from the request and was used to determine an exported resource.
So far, we handed the plain instance deserialized from the request body to the repository to persist it. That caused issues in PUT for create scenarios where the URI contains the identifier to be used for the aggregate to create and identifier generation being used in the backend. In that case the identifier submitted was never considered and subsequent requests would've created new instances, effectively breaking the idempotent nature of PUT.
We now make sure the backend identifier derived from the resource is set on the aggregate instance about to be created, so that backend can either accept that situation (new entity + manually defined identifier) or reject it (in case it insists on identifier generation).
In case PersistentEntities exposes a managed type whose raw type currently doesn't have a PersistentEntity registered, the constructor of UriToEntityConverter ran into a NullPointerException.
We now explicitly check for null and skip those types.
Filed DATAREST-1021 for further improvements in the 3.0 time frame.
Previously, when a request was sending an Accept header of some arbitrary *+json, the request was routed through the controllers and might have ended up producing a PersistentEntityResource that was then mapped using an uncustomized Jackson ObjectMapper. That has caused a huge JSON object to be unfolded which is highly undesirable.
We now only answer JSON requests to repository resources that contain an Accept header with any of the explicit JSON media types we got registered.
Tweaked the setup of the ExceptionHandlerExceptionResolver to not expose a bean in the first place but rather use the Spring MVC provided callbacks to register custom ones. We also now make sure MVC is bootstrapped property for integration tests through the inclusion of DelegatingWebMvcConfiguration.
We previously erroneously looked for a ~ in a JSON Pointer to indicate collection append in e.g. an add operation. We now also support the actually correct - keeping the original behavior for now to not break clients that currently make use of it.
Repositories in RepositoryCorsConfigurationAccessor may be null now. findCorsConfiguration returns null when no repositories are provided.
Original pull request: #257.
We now explicitly merge associations skipping the linkable ones. We also try to reuse the existing collections and maps if they're mutable falling back to a completely new one if not.
Extracted PropertyHandler and AssociationHandler implementations.
We now resolve the handler method argument type of an annotated repository event handler against the concrete handler type to make sure generics are resolved properly.
When merging collections on PATCH we now don't use the first collection item's type for all elements but inspect the values for each existing element found. When it comes to appending elements to the collection, wen now just stick to the declared component type as type hint for reading the provided value.
When copying the transient properties of an aggregate, we now try field based access first and fall back to accessor based copying in case both a setter and getter are exposed on the type.
Previously we always expected a field to be present which doesn't necessarily has to be the case.
Related ticket: DATAREST-986.
Jacksons ObjectMapper.readerForUpdate(…) unfortunately doesn't handle nested objects properly. We already have a manual merge process in place for PATCH requests but tweaking that to also handle PUT requests gracefully caused more complexity than anticipated.
We now switched to an object based merge so that we can read in the source JSON structure into a new object and then merge the objects.
Related pull request: #247.
We now use a Map property's generic type information to make sure we convert both the key and the value into the declared types. Previously we just used Object if the source value to map was null. Object is still used as fallback for raw maps though.
We now make sure that an @Order annotation on annotated event handler methods are considered and the methods are invoked in the defined order.
Non-annotation-based event handlers don't suffer from the same problem as they're ApplicationListener instances directly so that the container will enforce the correct ordering in case @Order is used or Ordered is implemented.
Some cleanup in EventHandlerMethod.
Original pull request: #248.