I have the following in my application.properties;
spring.datasource.username=${USERNAME}
spring.datasource.password=${PASSWORD}
spring.datasource.url=${DB_URL}
...
twitter.consumer.key=${CONSUMER_KEY}
twitter.consumer.secret=${CONSUMER_SECRET}
twitter.access.key=${ACCESS_KEY}
twitter.access.secret=${ACCESS_SECRET}
The top three properties are set by the environment when the application is pushed up to a heroku instance. The values that get set by the environment are then used to make connections to the database specific to that environment. This is all good.
The problem is with the last four. As these are sensitive information I need them to be injected by the environment also. I have then used autowiring to add these to a spring boot component.
#Value("${twitter.consumer.key}")
private String consumerKey;
#Value("${twitter.consumer.secret}")
private String consumerSecret;
#Value("${twitter.access.key}")
private String accessKey;
#Value("${twitter.access.secret}")
private String accessSecret;
Now, when I build the application it complains of being unable to resolve the ACCESS_KEY etc because I do not have these environment variables on my local machine.
Could not resolve placeholder 'CONSUMER_KEY' in string value "${CONSUMER_KEY}"
How can I build the application without explicitly setting these values? Is there, for example, some way of setting defaults for the application properties if they cannot be resolved?
With the #Value annotiation it is possible to set a default value:
#Value("${my.property:default}")
To prevent the build from failing you can specify default values for the application properties if the key could not be resolved. For example;
twitter.consumer.key=${CONSUMER_KEY:fallback}
twitter.consumer.secret=${CONSUMER_SECRET:fallback}
twitter.access.key=${ACCESS_KEY:fallback}
twitter.access.secret=${ACCESS_SECRET:fallback}
Related
I have a multi tenant environment so I need to change some path from application.properties in runtime to use the folder of specific tenant.
For example in my application properties:
image.avatars=C:/Users/Public/Pictures/Sample Pictures/${tenant}/Avatars/
in my class I use
#Autowired
private Environment env;
private static final String DIRECTORY_USER_IMAGE = "image.avatars";
.....Method
env.getRequiredProperty(DIRECTORY_USER_IMAGE)
I read about env.resolveRequiredPlaceholders but I don't understand how it can be used in my case since it has only one parameter like so env.resolveRequiredPlaceholders(TenantContext.getCurrentTenant()).
Is there a simple way to change the placeholder without manipulate String(with replace)?
I thought that env.resolveRequiredPlaceholders required the name of properties and the varargs of placeholder but it is different.
Thanks
You can use String.format().
Just use %s in properties
image.avatars=C:/Users/Public/Pictures/Sample Pictures/%s/Avatars/
And the in the code
String.format(imageavatars, tenant)
This might be not exactly what you want (because I struggle to understand your scenario), but what about putting
image.avatars=C:/Users/Public/Pictures/Sample Pictures/${tenant}/Avatars/
in your application.properties, and using
#Value("${image.avatars}")
private String DIRECTORY_USER_IMAGE;
in your bean/service and running the app with a command line argument like
--tenant="FooBar"
This would give DIRECTORY_USER_IMAGE the value C:/Users/Public/Pictures/Sample Pictures/FooBar/Avatars/ and you could change the CLI argument according to your needs. But be aware that DIRECTORY_USER_IMAGE is not static final anymore.
I hope I got your requirements right.
I have a large Spring web application, dating back several years. I need to update it to Spring Boot (corporate requirement). I'm well on my way - it starts (!), although there are some issues with properties being injected, which causes the app to fail.
Specifically, there are three huge config files per profile, eg qa_config.properties, qa_ehcache.xml, qa_monitoring.properties. At present I only care about qa_config.properties, which I have renamed to Spring Boot's preferred name, application-qa.properties, and application-qa_monitoring.properties
The application has a number of classes annotated with #Named (from the javax.ws.rs-api ) which are loaded early - so early that I need to inject properties in the constuctor:
package com.domain.app;
import org.springframework.beans.factory.annotation.Value;
import javax.inject.Named;
#Named
public class Foo {
// Cant use #Value here, it is not yet in the context
protected String bar; // lives in application-qa.properties
protected String qux; // lives in application-qa_monitoring.properties
public Foo(#Value("${application.property.named.bar}") String bar,
#Value("${monitoring.property.named.qux}") String qux) {
this.bar = bar;
this.qux = qux;
doSomeWork();
}
}
Properties files:
#application-qa.properties
application.property.named.bar=something
and
#application-qa_monitoring.properties
monitoring.property.named.qux=another_thing
My problem: I want to have both application-qa.properties and application-qa_monitoring.properties in context as soon as possible, and before the #Named classes are loaded.
To achieve this, I am running the application with an active profile of qa, which successfully adds that set of properties into the context.
I added this line to the application.properties file, to ensure that the other properties are loaded:
spring.profiles.include=${spring.profiles.active}_monitoring.properties
When I run the Spring Boot app, the output tells me
The following profiles are active: qa_monitoring.properties,qa
When debugging the Foo class, the value of bar is correct
But, the value of qux is null.
Am I missing something about the order in which properties files are loaded? I would have thought that the include line in application.properties would be sufficient to "flatten" the two files very early on, if one is in context, so both should be available?
What I could do instead is just throw all the vars in the two properties files into one, the application-qa.properties but I'd like, if possible, to keep them seperate and as close to the original structure as possible.
Thanks to pvpkiran and Andy Brown.
My application.properties file should have read
spring.profiles.include=${spring.profiles.active}_monitoring
ie, just adding another profile, in this case qa_monitoring - Spring automagically adds the application- prefix and the .properties suffix
The issue you are having is because you use a literal value instead of a lookup key in the #Value annotation of your qux value.
Replace
public Foo(#Value("${application.property.named.bar}") String bar,
#Value("monitoring.property.named.qux") String qux) {
With
public Foo(#Value("${application.property.named.bar}") String bar,
#Value("${monitoring.property.named.qux}") String qux) {
And it should work.
I'm using Hibernate and java.util.Logger class for logs in my project. I have a separate config file for both. I am able to switch between showing and not showing SQL queries by setting org.hibernate.SQL.level property to ALL in the log configuration file, but I can't figure out how to do it programatically (I want to handle this through run parameters but without having to use two seperate log configuration files).
So far I have tried setting this parameter in hibernate Configuration class, to no avail (properties are getting set, I double checked, but no queries show up).
Then I figured it must be handled by Logger class itself, but LogManager does not have any methods for setting a property. Browsing through the web guided me towards FileHandler class but I am able to set only the 'usual' log properties (like pattern, level, etc).
Does it mean I'm wrong in thinking I have to change the Logger class and it should in fact be set in hibernate's Configuration? If that's the case, why did it not work?
...I can't figure out how to do it programmatically (I want to handle this through run parameters but without having to use two separate log configuration files).
I would have assumed that the current situation solved the problem as log configurations are set using a run-time parameter. That said, the general approach is to get and store a strong reference to the logger and change the properties of that logger.
private static final Logger hardRef = Logger.getLogger("org.hibernate.SQL");
static {
if (traceSql()) {
hardRef.setLevel(Level.ALL);
}
}
private static boolean traceSql() {
return true; //#todo Add code.
}
PUsing Spring 3.2.0.release and JDK 1.6. I've a standalone Java program (NOT running inside tomcat etal) and I'm loading properties from a database.
I've used this excellent article as a base and it works perfectly. Using the PropertiesPrinter bean (defined there) as a base and adding getters I can do stuff like getFileLocation(), getPetDogsName() but then I need to have/create setter/getters for every property.
What I would like to have is a Spring Bean or normal Java class called DatabaseProperties with a method like getProperty("filelocation"); which I can use in my application (main)and so I can retrieve/get the value of the property filelocation which is somewhere inside the information collected by PropertyPlaceholderConfigurer.
I've done a lot of digging but can't seem to find the information I need or at least I'm not able to combine the gathered info into a working program as I'm not fluent with Spring....
Any hint/pointers/urls/code is higly appreciated. It's probably relative easy but it is still out of reach for me atm.
One solution for reading values set by the PropertyPlaceholderConfigurer, is to use the #Value annotation rather than a method for setting class member variables:
class MyClass {
#Value("${file.location}")
private String fileLocation;
...
}
Does using #{systemProperties['environment']} in the applicationcontext.xml file of Spring return the value associated with environment?
Or is there any way to ge the system variable value in the spring applicationcontext.xml file.
When I remember right, then there is a difference between:
You can access the system properties in different ways:
#{systemProperties['databaseName']}
#{systemProperties.databaseName}
${databaseName} //$ instead of # !!
With #{systemProperties['databaseName']} you have access to system-system-properties.
With #{systemProperties.databaseName} you have access to the system properties readed for example from the command line (-DdatabaseName="testDB").
With ${databaseName} you have access the the properties from the properties files loaded and provided for example by the PropertyPlaceholderConfigurer and to the system prooperties too
#Value("#{systemProperties['java.version']}")
private String javaVersionMap;
//Dont know how
//#Value("#{systemProperties.javav.version}")
//private String javaVersionDirect;
#Value("${java.version}")
private String javaVersionProp;
//-DcmdParam=helloWorld
#Value("#{systemProperties['cmdParam']}")
private String cmdParamMap;
#Value("#{systemProperties.cmdParam}")
private String cmdParamDirect;
#Value("${cmdParam}")
private String cmdParamProp
You can use all of them in a #Value annotation or the config.xml files (<property name="databaseName" value="#{systemProperties.databaseName}"/>)
One way to do this kind of thing is to use a PropertyPlaceholderConfigurer which can be configured to use the system properties.
I also noticed that the Spring 3.1 M1 blog entry talks about new stuff for accessing configuration information from "the environment". Of course, that is only a milestone ... not a production-ready release.