viernes, 4 de agosto de 2017

Overriding Spring Data REST Response Handlers to share news methods in all repositories

With my obsession for reusing all developments. I decided include all features from my module Spring Data Extension into Spring Data Rest Extension.  Hence, I can use all my extensions of spring data across rest in any proyect, without having to create mapping request in each one of the projects. In this line, I avoid repeat code and avoid have to do unit test by each repository that i make.

To explain how i have extended the spring data rest, i use like sample, the updating embedded documents that i made in spring data extension.

The more important is creates my own rest repository controller.

This class must have marked @RepositoryRestController annotation.



As we can see in the figure above, the mapping url is the union between BASE_MAPPING and "{id}/mergeembedded/{embeddedProperty}".


  • BASE_MAPPING: Contain the base path and repository name.
  • {id}: Identifier of the repository. In this point isn't used, but we'll see that the id is handled by PersistentEntityResourceHandlerMethodArgumentResolver.
  • {embeddedProperty}: Property name of the domain to get embedded information.


Another important thing in this class is get a invoker to execute, (in this case), the merge function. We get the invoker object using resourceInformation.getInvoker(). RootResourceInformation is the class that serves as bridge between repository rest controller and repository.

The next step is connect our repository invoker with RootResourceInformation. This connection is done by the class that resolves the arguments of the request.



The spring guys have provided us a method called postProcess where we can do this.

Spring Data Rest when processes the patch method does a merge between request content, (repository domain), and the persistent repository . This domain is sended to controller and is recoveried across getContext(). In my case, this operation don't want do it, because the merge embedded function already does this operation. I wan't get the original request domain in my custom controller. To change this behaviour, we have override PersistentEntityResourceHandlerMethodArgumentResolver.



Depending of a request header property and patch method is applied the update no merge feature or the default function.

The next step consists in says to spring data rest configuration that it uses the new funcionality. Hence, we override RepositoryRestMvcConfiguration. This class configure all necesary for spring data rest.



Finally, we going to create a configuration interface to do more easy the configuration to the developer.



How can we use this news features in our project?. We going to see a sample.

Steps:


  1. Define domains. Look at MongoDomain and MongoEmbeddedDomain.
  2. Define repository. Look at MongoRepository.
  3. Define @EnabledRepositoryExtensionRestMvc. Look at RestWebMvcConfiguration

Once defined all necesary in my project, we can use the news rest services methods across the curl utility or whatever. Look sample at integration test.


Full Sorce code.