Java system properties and environment variables
I think the difference between the two boils down to access. Environment variables are accessible by any process and Java system properties are only accessible by the process they are added to.
Also as Bohemian stated, env variables are set in the OS (however they 'can' be set through Java) and system properties are passed as command line options or set via setProperty()
.
How to add new System Properties in java
Either System.setProperty
or use the -Dname=value
flag when you start the JVM
how to set system property in spring boot application
Not good idea to set system variables from inside Java code.
Basically, variables are meant to keep the code free from having any variable values.
Use properties files to store your configurations. Spring Boot does a great job externalising your configurations.
It also let to you have environmental configurations in separate files and does a great job initialising it.
Refer to https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Use of SystemPropertyInitializer to set System Property before setting property placeholder
The easiest solution would be to pass in the environment property as a command-line argument, so it can be resolved as a system property.
If that's not an option you can implement a ApplicationContextInitializer
that promotes environment properties to system properties.
public class EnvironmentPropertyInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
boolean override = false; //change if you prefer envionment over command line args
@Override
public void initialize(final ConfigurableApplicationContext applicationContext) {
for (Entry<String, String> environmentProp : System.getenv().entrySet()) {
String key = environmentProp.getKey();
if (override || System.getProperty(key) == null) {
System.setProperty(key, environmentProp.getValue());
}
}
}
}
Here it looks like you're using Spring Batch Admin, so you can register your initializer with a slight addition to the web.xml
file:
<context-param>
<param-name>contextInitializerClasses</param-name>
<param-value>org.your.package.EnvironmentPropertyInitializer</param-value>
</context-param>
Adding Background Since a Comment Didn't Seem Sufficient: Here's the relevant classes and the order in which they are called/evaluated.
- The
ApplicationContextInitializer
tells the Spring Application how to load an application context and can be used to set bean profiles, and change other aspects of the context. This gets executed before the context gets completely created. - The
PropertyPlaceholderConfigurer
is aBeanFactoryPostProcessor
and callspostProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
. This modifies theBeanFactory
to allow for resolution of properties like${my.property:some.default}
when setting the properties of a bean as it is created by theBeanFactory
. - The
SystemPropertyInitializer
implementsInitializingBean
and callsafterPropertiesSet()
. This method runs after a bean is instantiated and the properties have been set.
So you're right that the SystemPropertyInitializer
will not help here since it evaluates after the properties are set on the PropertyPlaceholderConfigurer
. The ApplicationContextInitializer
, however, will be able to promote those environment properties to system properties so they can be interpreted by the XML.
And one more note that I forgot to mention, one of the first declared beans will need to be:
<context:property-placeholder/>
Though it seems redundant, it will allow your PropertyPlaceholderConfigurer
bean to evaluate ${ENVIRONMENT:hsql}
correctly by using the environment properties you just promoted.
How to set System property for a scalatest from sbt command line
Your third way almost works (if fork in Test := true
is set). But you have to change into the project first:
sbt/sbt '; project mllib; set javaOptions in Test +="-Dtest.num.points=500000"; \
test-only org.apache.spark.mllib.optimization.LBFGSSuite'
Set system property in jmockit unit test
Make sure you call System.setProperty("property.name", "https://justatest.com/dav/bulk");
before the class being tested is instantiated, otherwise the static field will always be null.
Consider using a @BeforeClass
setup method for this:
@BeforeClass
public static void setup() {
System.setProperty("property.name", "https://justatest.com/dav/bulk");
// Instantiate your CsvConfig instance here if applicable.
}
and then
@Test
public void getUrl(){
System.setProperty("property.name", "https://justatest.com/dav/bulk");
String fileUrl = csvConfig.getFileUrl();
assertEquals(fileUrl, "https://justatest.com/dav/bulk/otherstuff");
}
How to pass the -D System properties while testing on Eclipse?
Run -> Run configurations, select project, second tab: “Arguments”. Top box is for your program, bottom box is for VM arguments, e.g. -Dkey=value
.
Related Topics
Drawing an Object Using Getgraphics() Without Extending Jframe
Jtable with Titled Rows and Columns
How to Manage Exceptions Thrown in Filters in Spring
Try-Catch-Finally-Return Clarification
How to Get Absolute Path to File in /Resources Folder of Your Project
Variable's Scope in a Switch Case
Java, How to Add Library Files in Netbeans
Technique or Utility to Minimize Java "Warm-Up" Time
Error: Javafx Runtime Components Are Missing, and Are Required to Run This Application with Jdk 11
<Form Action="/Sampleservlet" Giving Me Exception
Java Error - Actual and Formal Argument Lists Differ in Length
Converting Secret Key into a String and Vice Versa
Optional Orelse Optional in Java
How to Run a Class in a War from the Command Line
Compiler Error When Declaring a Variable Inside If Condition and No Curly Braces