How do I set Spring properties in run configuration in Intellij - spring

I have the following code...
#Service
public class PropertiesService {
...
#Value("external.config.active") private String useExternalConfig
So in intellij I set the VM Options to...
-Dexternal.config.active=true
But when I debug in the application this.useExternalConfig.equals("external.config.active") is true.
What do I have to do to set a Spring property in the run configuration for IJ
Update I see it being supplied in the java command...
/.../java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:53192,suspend=y,server=n -Dexternal.config.active=true -javaagent:/.../Caches/IdeaIC2018.1/groovyHotSwap/gragent.jar -javaagent:/.../Caches/IdeaIC2018.1/captureAgent/debugger-agent.jar=file:/private/var/folders/3d/5f6dvvs573zg3ydvxbd0b0h40000gn/T/capture2.props -Dfile.encoding=UTF-8 -classpath

#Value takes a value expression ${...} or a SpEL expression #{...} as you haven't provided any of those the value as is will be used. To substitute a property you can use a value expression ${name.of.property}.
Or if you really like hardcore you can use SpEL #{#environment.getProperty('name.of.property')}. You see the value expression is easier.

This does seem to work...
#Value("${external.config.active}")
based on...
The actual value expression: e.g. "#{systemProperties.myProp}".
This is strange so if anyone can explain it further they get the check.

Related

Reading a configuration Value from YAML in Micronaut

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.

Remote directory expression string

In my project i use Spring Integration Sftp. I tried configure remoteDirectoryExpression with spEL, but the main problem, that SFTP folder value i store in application properties as sftp.folder=/test/.
handler.setRemoteDirectoryExpressionString("\'" + properties.getFolder() + "\'" + ".concat(headers['region'])");
properties.getFolder() is a class with #ConfigurationProperties.
This solution works fine, but i do not like it. So, it is possible somehow to write spEl expression without my curly braces?
but can`t get property from application.properties using expressions like ${}
That's right: you can't do that on this setter level because there is no properties placeholder knowledge because it is already a plain Java call.
You can do what you want via a #Value annotation on the property of the #Configuration class on or via #Bean method parameter:
#Bean
FtpMessageHandler ftpMessageHandler(#Value("'${sftp.folder}' + headers['region']") String remoteDirectory)

Optional environment variables in Spring app

In my Spring Boot app's application.properties I have this definition:
someProp=${SOME_ENV_VARIABLE}
But this is an optional value only set in certain environments, I use it like this
#Value("${someProp:#{null}}")
private String someProp;
Surprisingly I get this error when the env. var doesn't exist
Could not resolve placeholder 'SOME_ENV_VARIABLE' in string value "${SOME_ENV_VARIABLE}"
I was expecting Spring to just set a blank value if not found in any PropertySource.
How to make it optional?
Provide a default value in the application.properties
someProp=${SOME_ENV_VARIABLE:#{null}}
When used like #Value("${someProp}), this will correctly evaluate to null. First, if SOME_ENV_VARIABLE is not found when application.properties is being processed, its value becomes the string literal "#{null}". Then, #Value evaluates someProp as a SpEL expression, which results in null. The actual value can be verified by looking at the property in the Environment bean.
This solution utilizes the default value syntax specified by the PlaceholderConfigurerSupport class
Default property values can be defined globally for each configurer
instance via the properties property, or on a property-by-property
basis using the default value separator which is ":" by default and
customizable via setValueSeparator(String).
and Spring SpEL expression templating.
From Spring Boot docs on externalized configuration
Finally, while you can write a SpEL expression in #Value, such
expressions are not processed from Application property files.
This work for me:
spring.datasource.url=jdbc:mysql://${DB_IP:localhost}:3306/app
spring.datasource.username=${SPRING_DATASOURCE_USERNAME:mylocaluser}
spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:localpass}
Because this is probably interesting to others who come here, you can override any properties file w/ an env variable implicitly. Let's say you have property.
someapp.foo
Then you can define an env variable SOMEAPP_FOO (capital letters and . -> _ ) and spring will implicitly set the property from the env. variable.
Described further here: https://hughesadam87.medium.com/how-to-override-spring-properties-with-env-vars-82ee1db2ae78

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}

Spring #Value default property is not taken when runing JUnit tests

This is confusing. I have a property outerParameter, which is optionaly given among VM options when starting tomcat. I am using it by the following way in my logic:
#Value("${outerParameter:paused}")
private String featureStatus = "active";
public String getFeatureStatus() {
return featureStatus;
}
When starting tomcat without parameter - getFeatureStatus gives "paused", as expected. When starting with defined parameter - gives this parameter value, as expected.
The confusing part is that when I am runing JUnit tests for getFeatureStatus, it anyway gives me "active" and not the default "paused". The context for tests doesn't contain any <context:property-placeholder../> configuration.
I am trying to understand what I am missing, maybe somebody could give me a hand
I found this:
Spring #Value annotation not using defaults when property is not present
which could be the answer for my case too. It says "Perhaps initialization of property placeholder configurer fails due to missed properties file, so that placeholders are not resolved".
But if so, why it doesn't fail when starting tomcat without defined outerParameter?
Thanks
It means that the property is not loaded in the test case's classpath. Try loading the properties file in the context for test.

Resources