I have created a spring-boot application (2.6.4) and I want to integrate some plugins using p4fj. I have used p4fj before in non spring boot applications, but I see that now it has the p4fj-spring
to help on this process.
The idea is not only integrate the plugin methods, but check how to integrate some endpoints. For this purpose, I am following the official tutorial. Here, the point is, that for including the plugin endpoints (based on @RestController
, not reactive endpoints), is proposing:
private void registerMvcEndpoints(PluginManager pm) {
pm.getExtensions(PluginInterface.class).stream()
.flatMap(g -> g.mvcControllers().stream())
.forEach(r -> ((ConfigurableBeanFactory) beanFactory)
.registerSingleton(r.getClass().getName(), r));
applicationContext
.getBeansOfType(RequestMappingHandlerMapping.class)
.forEach((k, v) -> v.afterPropertiesSet());
}
The first part of the method is to obtain and register the needed classes from the plugin as beans, that is fine, for later register on the second part as endpoints. For this purpose, it is using a RequestMappingHandlerMapping.class
. If we follow the example on the tutorial, it is working fine for an application that has not own endpoints and it is only registering endpoints from an external plugin.
The problem I face is when I am trying to mix an application that already has some endpoints (defined by @RestController
), and I want to add some extra ones from one or more plugins. Running the previous code, I get an error telling that the application's endpoints cannot be registered as already exists.
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: Ambiguous handler methods mapped for '/health-check': {public void my.package.webservice.Info.healthCheck(javax.servlet.http.HttpServletRequest), public void my.package.webservice.Info.healthCheck(javax.servlet.http.HttpServletRequest)}
Seems that, when we are trying to include all endpoints from the plugin, it is also including again all applications endpoints, and therefore it faces the restriction of the uniqueness on the URL and method for any endpoint. I have debugged, and in fact seems RequestMappingHandlerMapping
has the information from the applications endpoints registered already by spring boot (and and the plugins also).
I have tried to create then a custom RequestMappingHandlerMapping
but this is only adding more duplications. And I have also tried to filter the applications endpoints (i.e. by package or url) from the registerMvcEndpoints
method shown before, but I have not luck with them, as we are not registering one by one, but all together in the afterPropertiesSet()
.
Then, the question is... How can I avoid the register of the endpoints that are already registered by the standard spring-boot initializator process? Or, there is any other way to register the plugin endpoints?