0

i am searching a solution to register an @RestController at runtime. I am currently registering the bean with ((GenericApplicationContext) applicationContext).registerBeanDefinition(name, beanDefinition); , but I can't use the endpoint specified in the @RestController bean.

What's the solution?

Dominic
  • 70
  • 1
  • 7

1 Answers1

0

I found a solution. The following post helped me: Is it possible to dynamically set RequestMappings in Spring MVC?

Quote: "When RequestMappingHandlerMapping is initialized, it scans the context and creates a map of all @RequestMappings that it needs to serve (presumably for performance reasons). If you dynamically register beans annotated with @Controller, they will not be picked them up. To retrigger this scan, you just need to call afterPropertiesSet() after you've added your beans."

So that's my solution:

@Qualifier("requestMappingHandlerMapping") RequestMappingHandlerMapping mappingHandlerMapping
BeanDefinition beanDefinition = new AnnotatedGenericBeanDefinition(TestController.class);
//noinspection ConstantConditions
String name = AnnotationBeanNameGenerator.INSTANCE.generateBeanName(beanDefinition, null);
((GenericApplicationContext) applicationContext).registerBeanDefinition(name, beanDefinition);

applicationContext.getBeansOfType(RequestMappingHandlerMapping.class).forEach((name, requestMappingHandlerMapping) -> {
   requestMappingHandlerMapping.getHandlerMethods().keySet().forEach(requestMappingHandlerMapping::unregisterMapping);
   requestMappingHandlerMapping.afterPropertiesSet();
});

Update 2022/07/04: Very important. When testing, I noticed that this solution makes existing routes no longer work. After a little debugging I found out that this is related to the fact that the routes (because internally a MultiValueMap is used) are added several times during a refresh. To fix this error the routes must first be removed from the RequestMappingHandlerMapping before a refresh. This can be done by using requestMappingHandlerMapping.getHandlerMethods().keySet().forEach(requestMappingHandlerMapping::unregisterMapping);

I have corrected the code snippet above.

Dominic
  • 70
  • 1
  • 7