Spring Boot @RestController enable/disable methods using properties [duplicate]
Asked Answered
C

2

12

I can enable/disable the whole @RestController using @ConditionalOnProperty, for example:

@RestController
@ConditionalOnProperty(name = "com.example.api.controller.decision.DecisionController.enabled", havingValue = "true")
@RequestMapping("/v1.0/decisions")
public class DecisionController {
}

The following configuration works fine. But I need to have more fine-grained control over this controller and enable/disable access to the certain methods inside, for example:

@RestController
@ConditionalOnProperty(name = "com.example.api.controller.decision.DecisionController.enabled", havingValue = "true")
@RequestMapping("/v1.0/decisions")
public class DecisionController {

    @ConditionalOnProperty(name = "com.example.api.controller.decision.DecisionController.create.enabled", havingValue = "true")
    @PreAuthorize("isAuthenticated()")
    @RequestMapping(method = RequestMethod.POST)
    public DecisionResponse create(@Valid @RequestBody CreateDecisionRequest request, Authentication authentication) {
        ...
    }

}

As you may see, I have added @ConditionalOnProperty to create method but this approach doesn't work and in case of enabled DecisionController the create method is also enabled even if com.example.api.controller.decision.DecisionController.create.enabled property is absent in my application.properties.

How to properly enable/disable create method in this case ?

Complication answered 8/4, 2018 at 7:10 Comment(4)
Just curious: what is the use-case? Why do you want to disable some methods?Grimy
@JBNizet I have the core project (Maven module) that defines the core endpoints and methods. Also, I have the project-specific Maven sub-module that includes the mentioned core module as the dependency. Based on the business needs and configuration in my sub-module project, I need to hide some of the core functionality(some methods) inherited from core project. Right now I can hide the whole controller but I need the more fine-grained control.Complication
The simplest way is probably to use a filter, and intercept requests to certain URLs / HTTP methods, and return a 404 if they're disabled.Grimy
Does this answer your question? Can a spring boot @RestController be enabled/disabled using properties?Smallclothes
B
8

You could also use aop to not proceed with method execution and return some status to the user. I'm using annotation here to mark/ identify disabled methods. You could add attributes to that annotation if you want to disable based on certain values in the attributes. Like you can add same property name and havingvalue and look for those and so on...

@Retention(RUNTIME)
@Target(METHOD)
public @interface DisableMe {}

Aspect:

@Aspect
@Component
public class DisableCertainAPI {

  @Autowired private HttpServletResponse httpServletResponse;

  @Pointcut(" @annotation(disableMe)")
  protected void disabledMethods(DisableMe disableMe) {
    // disabled methods pointcut
  }

  @Around("disabledMethods(disableMe)")
  public void dontRun(JoinPoint jp, DisableMe disableMe) throws IOException {
    httpServletResponse.sendError(HttpStatus.NOT_FOUND.value(), "Not found");
  }
}

and on target methods :

 @DisableMe
 @GetMapping(...)
 public ResponseEntity<String> doSomething(...){
  logger.info("recieved a request");
 }

you would see a response like :

{
  "timestamp": "2019-11-11T16:29:31.454+0000",
  "status": 404,
  "error": "Not Found",
  "message": "Not found",
  "path": "/xyz/...."
}
Bildungsroman answered 11/11, 2019 at 16:36 Comment(0)
R
2

Unfortunately, the @ConditionalOnProperty annotation can’t be used on a single @RequestMapping method. As a workaround, you can move the desired mapping to a separate controller bean.

http://dolszewski.com/spring/feature-toggle-spring-boot/

I hope this one may help the person who came to this page by the same question.

Rieth answered 11/11, 2019 at 13:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.