Could not resolve placeholder 'XXX' in string value "${XXX}" - spring-boot

In my spring boot example, I'd like to read environment variables from my local machine(Win 7).
#Data
#Component
public class EnvironmentVariableSystemProperties {
#Value("${java.home}")
private String javaHome;
#Value("${DATASTORE.DATASET}")
private String datastoreDataset;
#Value("${SPRINGA}")
private String springConfigName;
}
It works well when reading java.home and DATASTORE.DATASET which have been added in my OS environment variables before.
I just added a new variable SPRINGA. When running spring boot example, I got the error:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'SPRINGA' in string value "${SPRINGA}".
Should I restart up my machine to make the variable work?
I just restarted Eclipse, but it didn't work.

Restarting Eclipse with the Restart in the Menu doesn't work.
Exiting Eclipse and Running it again works.
How weird it is!

Related

Websphere Console 9.0 - where to specify Application specific files paths in websphere console

Websphere version 9.0 is installed in our RHEL 8.3 OS .
Now in that i have deployed one web app - .war file which contains multiple modules - webservice, web module etc.
This war is successfully deployed and i am able to start it also going to Websphere Enterprise Applications - AppName - START.
The app gets started with a success message.
Now the problem lies ahead. Our application requires a certain file bootstrap.properties.
This file has several configurations like jdbc params, jmx ports, jms configurations, jvm arguments, logging paths etc.
Once the web module of this app is run on <SERVER_IP>:9080/Context url, it throws error on GUI saying Unable to locate bootstrap.properties.
Analysing at the code level , found out that below code is throwing this error:
private static Properties config;
private static final String CONFIG_ROOT = System.getProperty("bootstrap.system.propertiespath");
private static final String configFile = "bootstrap.properties";
private JMXConfig() {
}
public static String getConfigRoot() {
if (CONFIG_ROOT == null) {
System.err.println("Not able to locate bootstrap.properties. Please configure bootstrap.system.propertiespath property.");
throw new ConfigException("Unable to locate bootstrap.properties.");
} else {
return CONFIG_ROOT + File.separator;
}
}
I wanted to know where can we specify the absolute paths in the websphere console where our property file can be read as a system argument once the application is loaded.
Since you're using System.getProperty() to read the property, it needs to be specified as a Java system property passed into the JVM. You can do that from the JVM config panel, adding it as either a custom property on the JVM or as a -D option in the server's generic JVM arguments.
Custom property: https://www.ibm.com/docs/en/was/9.0.5?topic=jvm-java-virtual-machine-custom-properties
Generic JVM argument: https://www.ibm.com/docs/en/was/9.0.5?topic=jvm-java-virtual-machine-settings (search for "Generic JVM arguments")
Note that if you use a custom property, you would simply set the "name" field to "bootstrap.system.propertiespath" and the "value" to the path you need; if you use a generic JVM argument, you'd add an argument with the structure "-Dbootstrap.system.propertiespath=/path/to/file".

Injecting Environment Variable into Groovy / Spring

I have a groovy class that uses spring injection to get a hostname (previously defined in application.properties). It works fine, the code looks like this:
import org.springframework.beans.factory.annotation.Value
... ...
#Value('${mycontext.var1}')
private String serverHost
Now, instead of using application.properties, I'd like to inject from an environment variable named SERVER_HOSTNAME. I tried the following, but it does not work.
#Value('${System.getenv("SERVER_HOSTNAME")}')
private String serverHost
It seems that the following piece of code should work:
#Value("#{environment.SERVER_HOSTNAME}")
private String serverHost

How to add an active spring profile from an environment variable?

Until now, I'm setting the following environment variable in my ~/.bash_profile :
export SPRING_PROFILES_ACTIVE=local
This set my active spring profile. But now, I want to add the local profile to other profiles defined in application.properties and not replace them.
In the Spring Boot documentation, there is a section about adding active profile, but I see nothing about adding active profile from an environment variable.
I've tried to set the SPRING_PROFILES_INCLUDE environment variable, but this has no effect.
How to do this?
P.S.: I'm using Spring Boot 1.4.2.
With default addition profile
You can introduce your own environment variable in the application.properties file, next to the defined profiles using an expression. For instance, if your current file looks like this:
spring.profiles.active=profile1,profile2
with a custom environment variable it will change into:
spring.profiles.active=profile1,profile2,${ADDITIONAL_APP_PROFILES:local}
where ADDITIONAL_APP_PROFILES is the name of the environment variable which you set instead of SPRING_PROFILES_ACTIVE.
The value local is used when the variable is not set on a current environment. In that case, the profile called local will be activated. If you don't set the default value and the environment variable is not present, the whole expression will be used as the name of an active profile.
Without default addition profile
If you like to avoid activating the default profile, you can remove the placeholder value and the comma before the variable expression:
spring.profiles.active=profile1,profile2${ADDITIONAL_APP_PROFILES}
but in that case the variable set on a current environment have to start with a comma:
export ADDITIONAL_APP_PROFILES=,local
The next sentence in the documentation you linked to:
Sometimes it is useful to have profile-specific properties that add to the active profiles rather than replace them. The spring.profiles.include property can be used to unconditionally add active profiles.
So you can launch your application with a command-line parameter:
-Dspring.profiles.include=${SPRING_PROFILES_INCLUDE}
This is an example of adding a programmatically additional active profile from system env or jvm arg.
#Configuration
public class ApplicationInitializer implements WebApplicationInitializer, ApplicationContextInitializer<ConfigurableWebApplicationContext> {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter("contextInitializerClasses", this.getClass().getCanonicalName());
}
#Override
public void initialize(ConfigurableWebApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
environment.addActiveProfile(System.getProperty("myProperty"));
environment.addActiveProfile(System.getEnv("myProperty"));
}
}
Here is not the Spring way, but also could be useful in some cases.
public static void main(String[] args) {
System.setProperty("spring.profiles.active", "local");
SpringApplication.run(MainApplication.class, args);
}
To support bash environment, available values are SPRING_PROFILES_ACTIVE and SPRING_PROFILES_DEFAULT
not, SPRING_PROFILES_INCLUDE
you probably have to resort commandline way -Dspring.profiles.include or pro grammatically workout with ConfigurableEnvironment
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/AbstractEnvironment.html#ACTIVE_PROFILES_PROPERTY_NAME

How to externalize configuration in Spring Boot using profiles?

I have an application where I would like to change a datasource password that is stored in a application.yml file. The password in the YML file is stored such as this:
----
spring:
profiles: production
datasource:
password: prodpassword
Note: I also have profiles for development and stage.
The password prop is set on a class using ConfigurationProperties such as follows:
#Component
#ConfigurationProperties(prefix="datasource")
public class DataSourceConnector {
private password;
public void setPassword(String password) {
this.password = password;
}
Now, I try to override the prodpassword with prodpa$$word via a command line arg but it doesn't work:
java -Dspring.profiles.active=production -jar /usr/share/myapp/myapp-1.0.jar --datasource.password='prodpa$$word'
I also tried creating an identical (except the new password) application.yml file outside of the jar. That doesn't work either.
java -Dspring.profiles.active=production -jar /usr/share/myapp/myapp-1.0.jar --spring.config.location=/usr/share/myapp/
Note: I left out the file name in the location param due to this note from http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config-profile-specific-properties:
If you have specified any files in spring.config.location, profile-specific variants of those files will not be considered. Use directories inspring.config.location if you also want to also use profile-specific properties.
How can I override datasource.password within the application.yml of the jar?
Edit:
The application is being started / stopped using supervisorctl.
After changing the config file that contains the java command, supervisorctl must reread the change:
supervisorctl reread
Next, activate the changes with:
supervisorctl update

#PropertySource working with spel (systemEnvironment and systemProperties)

I have in src/main/resources the following files
bpp-dev.properties
bpp-prod.properties
bpp-test.properties
Through my STS I can define the key envB, it in two places
how a VM argument such as -DenvB=dev
how an Environment such as Variable envB and Value prod
If in a Configuration class I have the following.
#Configuration
#PropertySource("classpath:/com/manuel/jordan/properties/bpp-${envB}.properties")
public class PropertiesConfiguration {
It works fine but always has preference the System Properties over Environment Variables, it is the default behaviour. I have no problem here.
But if I want work explicitly with Environment Variables, the following fails
#Configuration
#PropertySource("classpath:/com/manuel/jordan/properties/bpp-#{systemEnvironment['envB']}.properties")
public class PropertiesConfiguration {
Always I receive:
Caused by: java.io.FileNotFoundException:
class path resource
[com/manuel/jordan/properties/bpp-#{systemEnvironment['envB']}.properties]
cannot be opened because it does not exist
How I can fix this?
If I use the functional #PropertySource and just playing in the same #Configuration class I work with the following:
#Value("#{systemProperties['envB']}")
private String propertiesEnvB;
#Value("#{systemEnvironment['envB']}")
private String environmentEnvB;
to be printed later, both works fine.

Resources