The default exposure of repository methods is now controlled via RepositoryRestConfiguration.setExposeRepositoryMethodsByDefault(…). That allows us to remove the additional API from RepositoryDetectionStrategy as the mere detection is an orthogonal topic.
Also added RepositoryRestConfiguration.disableDefaultExposure() to set the RepositoryDetectionStategy to ANNOTATED and disables default method exposure in one go. That can be exposed via a Spring Boot configuration property downstream.
Removed Lombok constructor and accessor generation to avoid having to deal with the changed default in Lombok 1.16.20 not generating @ConstructorProperties by default anymore.
Spring Framework 5.0.2 changes the default for the Allow-Credentials header to false. We now adapted our test case to that and also drop the expectation to see the request URL in the Allow-Origin header as that is only returned if Allow-Credentials is true, which it now isn't by default.
Significantly refactored the way that patch path expressions are handled and evaluated. The new design is centered around SpelPath that is aware of the original path as well as the derived SpEL expression. That SpelPath then requires clients to bind it to a type so that the original path can be validated (and rejected if invalid) and provide API to read, set, copy and move values backed by the original path. Both SpelPath and TypedSpelPath instances are cached to avoid repeated creation.
PatchOperation implementations now provide more fluent factory methods, in some cases via intermediate builders. Removed a lot of obsolete code that created JsonNodes from a list of PatchOperations as we don't actually use that functionality anywhere. Removed obsolete generics where possible.
We now inspect the user class of the given bean type in BasePathAwareHandlerMapping.isHandler(…). We can't use AnnotationUtils as @RepositoryRestController is also annotated with @BasePathAwareController but must not be handled by this mapping.
Previously the SpEL expresssion created from JSON Patch path expressions were executed without double checking whether these paths actually exist on the target object in the first place. This is now in place.
Association links now explicitly indicate projections are available in case there are projection types registered for the association target type.
Original pull request: #273.
Switched from ProxyProjectionFactory.setResourceLoader(…) to ….setBeanClassLoader(…). Some generics polishing and removal of obsolete warnings supression.
We now also catch SpelEvaluationException in the attempt to set a null value for an expression as Spring 5 now reports a failed attempt (e.g. if the target type is not nullable) using that type whereas Spring 4.3 threw a NullPointerException.
Fixed the setup of our custom ExceptionHandlerExceptionResolver to conclude with a call to afterPropertiesSet() to make sure it's properly initialized.
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).
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.