How to get the value of Azure App Configuration Feature Flag with specific label from Spring boot? - spring-boot

I started using Azure App Configuration service and Feature Flags functionality in my project. I followed this documentation and was able to create a Spring boot project. I also created a FeatureFlagService class and autowired the FeatureManager class in it as shown below :
#Service
public class FeatureFlagService {
private FeatureManager featureManager;
public FeatureFlagService(FeatureManager featureManager) {
this.featureManager = featureManager;
}
public boolean isFeatureEnabled() {
return featureManager.isEnabledAsync("scopeid/MyFeature").block();
}
}
With this I get the value of the feature flag 'MyFeature' but with no label.
I have the same feature defined with different labels in Azure App Configuration as shown below.
I need to fetch the feature flag with specific label. How can I achieve it at runtime?
I don't see a way to do it using the FeatureManager class.

They only way to load from a label is by using spring.cloud.azure.appconfiguration.stores[0].feature-flags.label-filter, the Feature Management Library itself has no concept of a label.

Related

Enable by default an Actuator Endpoint in Spring Boot

I developed a small library that adds a custom endpoint for the actuator and I like to expose it by default. Spring Boot 2.7.4 only exposes by default health.
At the moment, what I am doing is registering an EnvironmentPostProcessor to add a property to include health,jwks at the last PropertySource in the environment. But it seems a little bit fragile. There are other libraries that have to export other endpoints by default (metrics, prometheus...)
This is what I am doing at the moment:
public class PoCEnvironmentPostProcessor implements EnvironmentPostProcessor {
private static final String PROPERTY_NAME = "management.endpoints.web.exposure.include";
#Override
public void postProcessEnvironment(
ConfigurableEnvironment environment,
SpringApplication application
) {
var propertySources = environment.getPropertySources();
propertySources.stream()
.filter(it -> it.containsProperty(PROPERTY_NAME))
.findFirst().ifPresentOrElse(source -> {
var property = source.getProperty(PROPERTY_NAME);
var pocSource = new MapPropertySource(PROPERTY_NAME, Map.of(PROPERTY_NAME, property + ",jwks"));
// Add the new property with more priority
propertySources.addBefore(source.getName(), pocSource);
}, () -> {
var pocSource = new MapPropertySource(PROPERTY_NAME, Map.of(PROPERTY_NAME, "health,jwks"));
propertySources.addLast(pocSource);
});
}
}
Is there any way to expose by default that allow me to add several endpoints in different libraries without playing to much with the property sources?
It’s not exactly clear to me if you’re asking how the client apps that use your library would enable specific endpoints, or if you are writing more than one library and want to expose different endpoints. I’ll answer both.
management.endpoints.web.exposure.include=comma-separated-endpoints would enable the listed endpoints without your library having to do anything. Your client apps can set this property in application.yml.
If you want to set this property by default in your library, one of the easiest ways is to put it in a property file, and load it as a #PropertySource on a #Configuration bean. I’m assuming your library is a starter and the #Configuration bean is auto-configured. If you don’t know how to create a starter, refer to this article.

How to prevent controller endpoints only available for a certain lifecycle environment in spring boot

Delete an article using DELETE /articles/:id
Delete all articles using DELETE /articles/
How can I make deletion support available only in dev environment and prevent it for test, staging, production environments in spring boot
First thing that comes to my mind would be adding a DeletionController which is created either based on a property or, in your case, on the active profile.
Something like:
#Profile("dev")
#RestController
public class DeletionController {
#DeleteMapping("articles")
public void deleteAll() {
//delete all articles
}
#DeleteMapping("articles/{id}")
public void delete(#PathVariable Integer id) {
//delete article for given id
}
}
Doing so Spring will only instantiate the DeletionController when the dev profile is active making the related endpoints available only in that case. You also have the possibility to have it active/inactive with more complex conditions like #Profile("dev & staging") or #Profile("dev & !production"). You can control the active profiles in your property file with the property spring.profiles.active.
The property approach would be using, instead of #Profile, the annotation #ConditionalOnProperty properly configured.

Spring: Azure Feature Manager Feature toggles Microsoft.Targeting bean not found

I am currently having a problem with the Azure feature manager. I used the following tutorial to add a feature toggle to my application: Link
This is working fine as long as we are talking about a manually set feature flag. As soon as the type of the feature is set to "Targeting" in Azure, the following code will result in an error.
featureManager.isEnabledAsync(FeatureToggle.OUR_FEATURE_TARGETING.key).block()
Specifically we will get No bean named 'Microsoft.Targeting' available in the spring error log. A client trying to acces an endpoint containing the above code will get a 500 with the error message Fail fast is set and a Filter was unable to be found: Microsoft.Targeting
Additional info
I am using Kotlin and Spring.
Setting the feature to "Time Based" will result in an error aswell.
The service calling the feature manager looks like this
#Autowired
private lateinit var featureManager: FeatureManager
fun feature(): String {
if (featureManager.isEnabledAsync(FeatureToggle.OUR_FEATURE_TARGETING.key).block() == true) {
return "feature A!"
} else {
return "feature B!"
}
And the FeatureToggle Enum looks like this
enum class FeatureToggle(val key: String) {
OUR_FEATURE_TARGETING("feature")
}
It doesn't go over it in that guide, but the built in Feature Flags are not configured to be on by default, then need to be built in an #Configuration file. More info can be found here https://microsoft.github.io/spring-cloud-azure/docs/azure-app-configuration/2.3.0/reference/html/index.html#built-in-feature-filters

Quarkus : Change OpenApi authorization url at runtime

I am currently experimenting with quarkus and cannot find a way to change some openapi information at runtime (here, I want the authorization url to change depending on the environment).
It should be possible by using OASFilter and feeding information from environment variables but OASFilter seems to be initialized at build time. I added a log in the filterSecurityScheme method and the log is displayed at build (by quarkus-maven-plugin) and then never displayed at runtime.
The code is pretty simple :
public class OASSecurityConfiguration implements OASFilter {
#Override
public SecurityScheme filterSecurityScheme(final SecurityScheme securityScheme) {
securityScheme.getFlows().
getImplicit().
setAuthorizationUrl(ConfigProvider.getConfig().getValue("quarkus.oidc.auth-server-url", String.class)+"/protocol/openid-connect/auth");
return securityScheme;
}
}
Is there any other way to change openapi specs at runtime from environment variables or to prevent the OASFilter to be initialized at build time ?
Thanks.
Since Quarkus v2 there is now a config option quarkus.smallrye-openapi.always-run-filter (docs) that enables you to run the OASfilter everytime the openapi document is served.

Dependency Injection Android

I am not sure how to use Dependency Injection on Xamarin Android project solution. Currently my Android solution holds a reference to another class library solution. I have used Unity on my service layer and registered the container via WebApiConfig.cs.
My question is, how do i go about using Unity on Android side in order to run on start up, would be grateful if code was included. I dont want to new-up the container through main activity of Android. I want the container to register behind the process i.e. AppStart or Global asax where it does it for you for MVC apps. Is there a way to do it for Android? Also I noticed on Main Activity I am unable to create constructor. I guess this isnt possible but how do I go about holding object reference to my Class Library solution ? example that i attempted to do:
private IExample _ex;
MainActivity(IExample ex){
_ex = ex; //depedency Injection rather than newing it up
}
public void DoSomething(){
_ex.HelloWorld();
}
Is there a way to do it via Attribute ? Also for each of my layer do I need to install and create container in order to resolve current solution dependency ? or can I use container from android which would resolve all dependency in each layer as DDD architecture goes from outer to inner ?
In terms of setting up DI at startup you can create a custom Application implementation like so:
// Must include this attribute so that Android knows we want to use this as our Application implementation
[Application(Icon = "#drawable/Icon", Label = "#string/ApplicationName")]
public class MyApplication : Application
{
public override void OnCreate()
{
base.OnCreate();
// Do your DI initialization/registration here
}
}
I'm not sure exactly what you mean by not being able to create a constructor on the main activity. You can create constructors for any activity you feel like. You don't always see it though because people tend to put their initialization logic in OnCreate.

Resources