We have a use case where we want a set of endpoints to be enabled in every environment except the production environment. Rather than implementing a custom security implementation for this use case, our idea was to use a variation of Spring's Conditional annotation to only enable the controller in non-production environments.
Our initial attempt was to use @ConditionalOnExpression by injecting a dynamic system property that specifies the type of environment (eg. dev, test, prod, etc.) and to match that property against a regular expression, but we have not been able to get the SpEL expressions to resolve properly in a way that suits our needs.
@RestController
@ConditionalOnExpression("${property.name} matches ^((?!prod).)*$")
public class TestDataController
We have also considered using @ConditionalOnProperty, but there seems to be no way to allow this property to accept multiple valid values.
@RestController
@ConditionalOnProperty(
value = "property.name",
havingValue = "value1" or "value2",
matchIfMissing = true)
public class TestDataController
Our last attempt was to write a custom class extending Spring's Conditional class to suit our needs. This works for now, but it is relying on Java file I/O, which we would like to avoid if possible.
Any ideas?
UPDATE 29 May 19
We were able to use the following solution to solve our problem:
public class NotInProductionCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
final String env = context.getEnvironment().getProperty("property.name");
if (env == null || env.isEmpty()) {
return true;
}
return !env.contains("prod");
}
}
@RestController
@Conditional(NotInProductionCondition.class)
public class TestDataController
You can use @Profile annotation to instantiate a bean depending on a profile set in your environment.
@RestController
@Profile("!prod")
class MyController {
...
}
If you don't use profiles in your environment you most likely using some type of environment variable to specify the environment name, I suppose. You can make it a spring profile like this
spring.profiles.active = ${environmentName}