spring-framework / org.springframework.core.env

Package org.springframework.core.env

Types

CommandLinePropertySource

abstract class CommandLinePropertySource<T : Any> : EnumerablePropertySource<T>

Abstract base class for PropertySource implementations backed by command line arguments. The parameterized type T represents the underlying source of command line options. This may be as simple as a String array in the case of SimpleCommandLinePropertySource, or specific to a particular API such as JOpt's OptionSet in the case of JOptCommandLinePropertySource. Purpose and General Usage For use in standalone Spring-based applications, i.e. those that are bootstrapped via a traditional main method accepting a String[] of arguments from the command line. In many cases, processing command-line arguments directly within the main method may be sufficient, but in other cases, it may be desirable to inject arguments as values into Spring beans. It is this latter set of cases in which a CommandLinePropertySource becomes useful. A CommandLinePropertySource will typically be added to the Environment of the Spring ApplicationContext, at which point all command line arguments become available through the Environment#getProperty(String) family of methods. For example:

 public static void main(String[] args) { CommandLinePropertySource clps = ...; AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.getEnvironment().getPropertySources().addFirst(clps); ctx.register(AppConfig.class); ctx.refresh(); }
With the bootstrap logic above, the AppConfig class may @Inject the Spring Environment and query it directly for properties:
 @Configuration public class AppConfig { @Inject Environment env; @Bean public void DataSource dataSource() { MyVendorDataSource dataSource = new MyVendorDataSource(); dataSource.setHostname(env.getProperty("db.hostname", "localhost")); dataSource.setUsername(env.getRequiredProperty("db.username")); dataSource.setPassword(env.getRequiredProperty("db.password")); // ... return dataSource; } }
Because the CommandLinePropertySource was added to the Environment's set of MutablePropertySources using the #addFirst method, it has highest search precedence, meaning that while "db.hostname" and other properties may exist in other property sources such as the system environment variables, it will be chosen from the command line property source first. This is a reasonable approach given that arguments specified on the command line are naturally more specific than those specified as environment variables.

As an alternative to injecting the Environment, Spring's @Value annotation may be used to inject these properties, given that a bean has been registered, either directly or through using the <context:property-placeholder> element. For example:

 @Component public class MyComponent { @Value("my.property:defaultVal") private String myProperty; public void getMyProperty() { return this.myProperty; } // ... }
Working with option arguments

Individual command line arguments are represented as properties through the usual PropertySource#getProperty(String) and PropertySource#containsProperty(String) methods. For example, given the following command line:

--o1=v1 --o2
'o1' and 'o2' are treated as "option arguments", and the following assertions would evaluate true:
 CommandLinePropertySource ps = ... assert ps.containsProperty("o1") == true; assert ps.containsProperty("o2") == true; assert ps.containsProperty("o3") == false; assert ps.getProperty("o1").equals("v1"); assert ps.getProperty("o2").equals(""); assert ps.getProperty("o3") == null; 
Note that the 'o2' option has no argument, but getProperty("o2") resolves to empty string ("") as opposed to null, while getProperty("o3") resolves to null because it was not specified. This behavior is consistent with the general contract to be followed by all PropertySource implementations.

Note also that while "--" was used in the examples above to denote an option argument, this syntax may vary across individual command line argument libraries. For example, a JOpt- or Commons CLI-based implementation may allow for single dash ("-") "short" option arguments, etc.

Working with non-option arguments

Non-option arguments are also supported through this abstraction. Any arguments supplied without an option-style prefix such as "-" or "--" are considered "non-option arguments" and available through the special property. If multiple non-option arguments are specified, the value of this property will be a comma-delimited string containing all of the arguments. This approach ensures a simple and consistent return type (String) for all properties from a CommandLinePropertySource and at the same time lends itself to conversion when used in conjunction with the Spring Environment and its built-in ConversionService. Consider the following example:

--o1=v1 --o2=v2 /path/to/file1 /path/to/file2
In this example, "o1" and "o2" would be considered "option arguments", while the two filesystem paths qualify as "non-option arguments". As such, the following assertions will evaluate true:
 CommandLinePropertySource ps = ... assert ps.containsProperty("o1") == true; assert ps.containsProperty("o2") == true; assert ps.containsProperty("nonOptionArgs") == true; assert ps.getProperty("o1").equals("v1"); assert ps.getProperty("o2").equals("v2"); assert ps.getProperty("nonOptionArgs").equals("/path/to/file1,/path/to/file2"); 

As mentioned above, when used in conjunction with the Spring Environment abstraction, this comma-delimited string may easily be converted to a String array or list:

 Environment env = applicationContext.getEnvironment(); String[] nonOptionArgs = env.getProperty("nonOptionArgs", String[].class); assert nonOptionArgs[0].equals("/path/to/file1"); assert nonOptionArgs[1].equals("/path/to/file2"); 

The name of the special "non-option arguments" property may be customized through the #setNonOptionArgsPropertyName(String) method. Doing so is recommended as it gives proper semantic value to non-option arguments. For example, if filesystem paths are being specified as non-option arguments, it is likely preferable to refer to these as something like "file.locations" than the default of "nonOptionArgs":

 public static void main(String[] args) { CommandLinePropertySource clps = ...; clps.setNonOptionArgsPropertyName("file.locations"); AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.getEnvironment().getPropertySources().addFirst(clps); ctx.register(AppConfig.class); ctx.refresh(); }
Limitations This abstraction is not intended to expose the full power of underlying command line parsing APIs such as JOpt or Commons CLI. It's intent is rather just the opposite: to provide the simplest possible abstraction for accessing command line arguments after they have been parsed. So the typical case will involve fully configuring the underlying command line parsing API, parsing the String[] of arguments coming into the main method, and then simply providing the parsing results to an implementation of CommandLinePropertySource. At that point, all arguments can be considered either 'option' or 'non-option' arguments and as described above can be accessed through the normal PropertySource and Environment APIs.

CompositePropertySource

open class CompositePropertySource : EnumerablePropertySource<Any>

Composite PropertySource implementation that iterates over a set of PropertySource instances. Necessary in cases where multiple property sources share the same name, e.g. when multiple values are supplied to @PropertySource.

As of Spring 4.1.2, this class extends EnumerablePropertySource instead of plain PropertySource, exposing #getPropertyNames() based on the accumulated property names from all contained sources (as far as possible).

JOptCommandLinePropertySource

open class JOptCommandLinePropertySource : CommandLinePropertySource<OptionSet>

CommandLinePropertySource implementation backed by a JOpt OptionSet. Typical usage Configure and execute an OptionParser against the String[] of arguments supplied to the main method, and create a JOptCommandLinePropertySource using the resulting OptionSet object:

 public static void main(String[] args) { OptionParser parser = new OptionParser(); parser.accepts("option1"); parser.accepts("option2").withRequiredArg(); OptionSet options = parser.parse(args); PropertySource ps = new JOptCommandLinePropertySource(options); // ... }
See CommandLinePropertySource for complete general usage examples.

Requires JOpt Simple version 4.3 or higher. Tested against JOpt up until 5.0.

PropertySourcesPropertyResolver

open class PropertySourcesPropertyResolver : AbstractPropertyResolver

PropertyResolver implementation that resolves property values against an underlying set of PropertySources.

SimpleCommandLinePropertySource

open class SimpleCommandLinePropertySource : CommandLinePropertySource<CommandLineArgs>

CommandLinePropertySource implementation backed by a simple String array. Purpose This CommandLinePropertySource implementation aims to provide the simplest possible approach to parsing command line arguments. As with all CommandLinePropertySource implementations, command line arguments are broken into two distinct groups: option arguments and non-option arguments, as described below (some sections copied from Javadoc for SimpleCommandLineArgsParser): Working with option arguments Option arguments must adhere to the exact syntax:

--optName[=optValue]
That is, options must be prefixed with "--", and may or may not specify a value. If a value is specified, the name and value must be separated without spaces by an equals sign ("="). Valid examples of option arguments
 --foo --foo=bar --foo="bar then baz" --foo=bar,baz,biz
Invalid examples of option arguments
 -foo --foo bar --foo = bar --foo=bar --foo=baz --foo=biz
Working with non-option arguments Any and all arguments specified at the command line without the "--" option prefix will be considered as "non-option arguments" and made available through the #getNonOptionArgs() method. Typical usage
 public static void main(String[] args) { PropertySource ps = new SimpleCommandLinePropertySource(args); // ... }
See CommandLinePropertySource for complete general usage examples. Beyond the basics

When more fully-featured command line parsing is necessary, consider using the provided JOptCommandLinePropertySource, or implement your own CommandLinePropertySource against the command line parsing library of your choice!

SystemEnvironmentPropertySource

open class SystemEnvironmentPropertySource : MapPropertySource

Specialization of MapPropertySource designed for use with system environment variables. Compensates for constraints in Bash and other shells that do not allow for variables containing the period character and/or hyphen character; also allows for uppercase variations on property names for more idiomatic shell use.

For example, a call to getProperty("foo.bar") will attempt to find a value for the original property or any 'equivalent' property, returning the first found:

  • foo.bar - the original name
  • foo_bar - with underscores for periods (if any)
  • FOO.BAR - original, with upper case
  • FOO_BAR - with underscores and upper case
Any hyphen variant of the above would work as well, or even mix dot/hyphen variants.

The same applies for calls to #containsProperty(String), which returns true if any of the above properties are present, otherwise false.

This feature is particularly useful when specifying active or default profiles as environment variables. The following is not allowable under Bash:

spring.profiles.active=p1 java -classpath ... MyApp
However, the following syntax is permitted and is also more conventional:
SPRING_PROFILES_ACTIVE=p1 java -classpath ... MyApp

Enable debug- or trace-level logging for this class (or package) for messages explaining when these 'property name resolutions' occur.

This property source is included by default in StandardEnvironment and all its subclasses.

Exceptions

MissingRequiredPropertiesException

open class MissingRequiredPropertiesException : IllegalStateException

Exception thrown when required properties are not found.

Functions

get

operator fun PropertyResolver.get(key: String): String

Extension for PropertyResolver.getRequiredProperty providing Array like getter.