Reading a configuration Value from YAML in Micronaut - yaml

How to read a value from application.yml in my Micronaut project? I can clearly see annotation is resolved to proper value (true in this case), but it is not applied to the variable (stays as default false). I've tried using #Value and #ConfigurationProperties

In a comment the OP has indicated that they are doing new FeatureToggleService(). Creating your own instance of the object is the problem. Instead of using new, let the DI container create and manage the instance. If you do, then #Value will be relevant.
See https://github.com/jeffbrown/filiard/blob/f6f704fb95d7821919748bb41968f87d11cee07b/src/main/java/filiard/DemoController.java and https://github.com/jeffbrown/filiard/blob/f6f704fb95d7821919748bb41968f87d11cee07b/src/main/java/filiard/FlagHelper.java for a working example.

UPDATE:
Based on additional information this is not the correct answer!!!
As pointed out, #Value can be private, but Micronaut advices against it.
Short answer, it is because it is private. Wrong
From the documentation:
The #Value annotation accepts a string that can have embedded placeholder values (the default value can be provided by specifying a
value after the colon : character). Also try to avoid setting the
member visibility to private, since this requires Micronaut Framework
to use reflection. Prefer to use protected.
Also, consider using #Property instead of #Value. Still valid
https://docs.micronaut.io/latest/guide/#valueAnnotation
NOTE:
The Micronaut framework does not inspect a manually created instance, even if it is instantiated in a #Factory, unlike other frameworks.

Related

When using ConfigurationProperties with a camelCase prefix, how do I solve "Prefix must be in canonical form"?

I had a property configured in my yml as
foobar:
baz: 7
and a configuration class annotated with
#ConfigurationProperties(prefix = "foobar")
and everything was working fine.
The code in my organization is generally camelCase, so I renamed both the property and prefix to fooBar. IntelliJ is now highlighting the prefix = "foobar" line with the error, "Prefix must be in canonical form". What can I do, while keeping camelCasing in the yml config?
Spring Boot supports multiple formats of property names, but encourages you to access them in a canonical way.
Per Property Binding in Spring Boot 2.0:
It turns out the idea of relaxed property names is much easier to implement if you restrict it to one direction. You should always access properties in code using a canonical form, regardless of how they are represented in the underlying source.
The ConfigurationPropertyName class enforces these canonical naming rules, which basically boil down to “use lowercase kebab-case names”.
So, for example, you should refer to a property in code as person.first-name even if person.firstName or PERSON_FIRSTNAME is used in the underlying source.
You can keep your config yml in camel case:
fooBar:
baz: 7
but change the access in the configuration class annotation to use kebab-case:
#ConfigurationProperties(prefix = "foo-bar")

How to load a bean only if the property value is other than a fixed value

I am facing a situation in which a bean should be created by the application context only if the property contains any other value than a specific value.
i.e... one property file.path= /specific/path, If the value is other than this then bean should be loaded.
I can see that there is #ConditionalOnProperty (name="file.path", havingValue="....") out of the box but in my case, I am looking a property like havingValueOtherThan="..." or similar kind of property or annotation if it is there out of the box in the spring.
There are many possible options, besides profiles that were stated in comments, here are 2 options:
Option 1
Use #ConditionalOnExpression with any SPeL expression you wish
Option 2
You can always create your own conditional annotation with any logic:
Create an annotation that will depict your own business case with a #Conditional on it.
Then Implement the conditional logic of your choice. Here is an example of achieving this.
BTW, the profiles that mentioned in comments are using Conditionals engine under the hood (The #Profile annotation has a #Conditional({ProfileCondition.class}) in its definition since Spring 4.x)

Kotlin Spring boot #Value annotation process

#Value("\${datasource.host}")
private val host: String = ""
I wrote the following code in KOTLIN and it worked fine.
I don't understand how the host was injected into the host.
In my knowledge, the value should not be injected because the host variable is val.
How does this code work?
Short answer: Spring is magical!
For a Kotlin property, val doesn't necessarily mean that the property is constant.  (It's not an exact equivalent of Java final here.)  It simply means that there's a get() method but no set() method.
That leaves open the possibility for the value to change some other way.  (For example, the property could have a custom getter which returned different values.)
I'm not sure quite how Spring works its magic; it may be able to set the property's backing field directly, or it may create a hidden subclass which can.  In any case, it's perfectly capable of setting val properties.  (You can also see this in Hibernate.)

How to set Spring camel case property with uppercase environment variable?

I have some code to load a value as such in my Spring application:
#Component
public class MyElasticRestService {
#Value("${elasticApi.baseURL}")
private String elasticApiBaseUrl;
According to the Spring docs, I should be able to use a relaxed binding that comes from an uppercase environment variable such as ELASTIC_API_BASE_URL or ELASTICAPI_BASEURL. But I'm confused which is correct. Both don't seem to work so I am wondering how to debug what is actually picked up.
I've loaded Spring Boot Actuator to view the configprops endpoint. But it doesn't have anything on the elasticApi prefix.
What should the correct environment variable be and how can I see how it gets translated and picked up by the application?
The #Value annotation doesn't support relaxed bindings. Therefore you could use a class annotated with #ConfigurationProperties or you use a RelaxedPropertyResolver to get the value from the environment.
According to https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-vs-value, it is now very possible simply with #Value as long as you use kebab-case (all lower case with dash) for the name e.g. #Value("config.refresh-rate")
Instead of trying to make it an UPPER_SNAKE_CASE, you can put it in your application.yaml file, this way:
elasticApi.baseURL: ${ELASTIC_API_BASE_URL:defaultvalue}
or this way doesn't really matter:
elasticApi:
baseURL: ${ELASTIC_API_BASE_URL:defaultvalue}

How to understand exact value ScopedProxyMode.Default for certain application?

according ScopedProxyMode enum documentation
value
DEFAULT
Default typically equals NO, unless a different default has been configured at the component-scan instruction level.
I use spring boot and I have not ideas how can I understand which ScopedProxyMode uses
Is where way to know this information?
If you take a look at the #SpringBootApplication annotation, you will find that it is internally referencing a #ComponentScan annotation.
Which in turn controls the ScopedProxyMode setting. If left unspecified (like in our case), it defers the decision to the ClassPathBeanDefinitionScanner class.
Which ClassPathBeanDefinitionScanner finally contains a real default: ScopedProxyMode=no. So to answer your question: if you have not explicitly change it, the default Spring Boot setting for scopedProxyMode will be false.

Resources