Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a spring boot @RestController be enabled/disabled using properties?

Given a "standard" spring boot application with a @RestController, eg

@RestController @RequestMapping(value = "foo", produces = "application/json;charset=UTF-8") public class MyController {     @RequestMapping(value = "bar")     public ResponseEntity<String> bar(         return new ResponseEntity<>("Hello world", HttpStatus.OK);     } } 

Is there an annotation or technique that prevents the endpoint from starting at all if/unless a certain application property exists/doesn't exist.

Note: Testing a property inside the method and exploding is not a solution, because the endpoint will exist.

I don't care about the granularity: ie enabling/disabling just a method or the whole class are both fine.


Because a profile is not a property, control via profiles does not solve my problem.

like image 924
Bohemian Avatar asked Apr 30 '15 02:04

Bohemian


2 Answers

I found a simple solution using @ConditionalOnExpression:

@RestController @ConditionalOnExpression("${my.controller.enabled:false}") @RequestMapping(value = "foo", produces = "application/json;charset=UTF-8") public class MyController {     @RequestMapping(value = "bar")     public ResponseEntity<String> bar(         return new ResponseEntity<>("Hello world", HttpStatus.OK);     } } 

With this annotation added, unless I have

my.controller.enabled=true 

in my application.properties file, the controller won't start at all.

You can also use the more convenient:

@ConditionalOnProperty("my.property") 

Which behaves exactly as above; if the property is present and "true", the component starts, otherwise it doesn't.

like image 122
Bohemian Avatar answered Oct 14 '22 12:10

Bohemian


Adding to this question and another question here.

This is my answer:

I would actually used the @RefreshScope Bean and then when you want to stop the Rest Controller at runtime, you only need to change the property of said controller to false.

SO's link referencing to changing property at runtime.

Here are my snippets of working code:

@RefreshScope @RestController class MessageRestController(     @Value("\${message.get.enabled}") val getEnabled: Boolean,     @Value("\${message:Hello default}") val message: String ) {     @GetMapping("/message")     fun get(): String {         if (!getEnabled) {             throw NoHandlerFoundException("GET", "/message", null)         }         return message     } } 

And there are other alternatives of using Filter:

@Component class EndpointsAvailabilityFilter @Autowired constructor(     private val env: Environment ): OncePerRequestFilter() {     override fun doFilterInternal(         request: HttpServletRequest,         response: HttpServletResponse,         filterChain: FilterChain     ) {         val requestURI = request.requestURI         val requestMethod = request.method         val property = "${requestURI.substring(1).replace("/", ".")}." +                 "${requestMethod.toLowerCase()}.enabled"         val enabled = env.getProperty(property, "true")         if (!enabled.toBoolean()) {             throw NoHandlerFoundException(requestMethod, requestURI, ServletServerHttpRequest(request).headers)         }         filterChain.doFilter(request, response)     } } 

My Github explaining how to disable at runtime

like image 38
David Latief Budiman Avatar answered Oct 14 '22 11:10

David Latief Budiman