I am injecting a value to a variable with #Value. For some reason, when I have the default value, it only uses it, it doesn't look for it in the properties file. When I'm not using the default value, it does inject the value from the properties file. No other configurations were changed.
#Value("${migration.paths:#{'classpath:db/migration'}}")
private String dbMigrationPaths;
(I'm using SPEL in the default value because it has slashes)
The property file configuration:
#Bean
public static PropertySourcesPlaceholderConfigurer configDataSourcesPropertyFile() {
PropertySourcesPlaceholderConfigurer bean = new PropertySourcesPlaceholderConfigurer();
bean.setLocations(new ClassPathResource[]{
new ClassPathResource("/file1"),
new ClassPathResource("/file2")
});
bean.setIgnoreUnresolvablePlaceholders(true);
bean.setIgnoreResourceNotFound(true);
return bean;
}
Both are properties files, and the property in question resides in file1 and not in file2
Do you have two property placeholders in your project? If yes, you may be running into this bug documented here: https://jira.spring.io/browse/SPR-9989. See at the end there is a link to suggested workaround.
Related
I am creating a spring-boot application which also creates bean for one of the classes of an external lib, this external java bean needs java.util.properties as one of the constructor parameter. Although I can use configurationPropeties with prefix to read properties from the spring boot loaded property file and convert it to java.util.properties.However, I don't want any additional prefix in the property file. is there any other way where I can convert the spring-boot loaded env or property source to java.util.properties
here is the code for reference
#Configuration
public class AppConfig {
#ConfigurationProperties(prefix = "some.prefix")
#Bean
public Properties getProperties() {
return new Properties();
}
#Bean
public ExternalClass externalClass() throws ConfigException {
return ExternalClass.getInstance(getProperties());
}
}
the above code work nicely, but I need to add an unnecessary prefix to the properties for conversion. could someone suggest any other approach apart from adding prefix to the propeties
Take a look at this documentation. It explains property binding techniques used in spring-boot.
I've been searching forever for an issue similar to mine, but wasn't able to find one. Thus, I hope it's not a duplicate post.
Well,
I'm using spring integration to search for documents in my mongodb. Once it finds one, it sends the payload to another method.
I have a property file that I want to be resolved on this find and send configuration, so I use placeholders instead of static values.
Here's my xml:
<int:inbound-channel-adapter id="sendClientMailInboundAdapter"
expression="#repository.findClient()"
channel="sendClientMailChannel"
auto-startup="${send.mail.active:false}">
<int:poller fixed-rate="${send.mail.poller.time:60}" time-unit="SECONDS" max-messages-per-poll="1" />
</int:inbound-channel-adapter>
<int:channel id="sendClientMailChannel" />
<int:service-activator input-channel="sendClientMailChannel" expression="#service.sendClientMail(payload)" />
Right.
Now.. I've got an AppConfig class which loads the property file.
#Configuration
#PropertySource("file://${appconfig.root}/appconfig.properties")
public class AppConfig {
public static Environment env;
...
#Bean
public static PropertySourcesPlaceholderConfigurer appConfigConfigurer(Environment env) {
AppConfig.env = env;
PropertySourcesPlaceholderConfigurer appConfigConfigurer = new PropertySourcesPlaceholderConfigurer();
appConfigConfigurer.setIgnoreUnresolvablePlaceholders(true);
appConfigConfigurer.setIgnoreResourceNotFound(true);
return appConfigConfigurer;
}
}
So.. My problem is the default value.
If I do NOT specify the default value, spring resolves the placeholder. If it's specified, though, it seems spring ignores the placeholder (maybe it doesn't wait for it to resolve) and set the default value instead!
I could use context:property-placeholder location. I've done that and it worked, but since I'm already loading the file on my configuration class, I'd rather have spring read properties from there so I would not have to remember to adjust two files in case property file changes its folder, for instance.
My question: Is there a way to tell spring to wait for the placeholder to resolve before looking at the default value?
edit: Just so people know.. I changed xml to java config, using placeholder / default value like before and it worked perfectly.
Here is the equivalent snippet:
#InboundChannelAdapter(value = "sendClientMailChannel", autoStartup="${send.mail.active:false}",
poller = #Poller(fixedRate="${send.mail.poller.time.in.millis:60000}", maxMessagesPerPoll="1"))
public Client findClient() {
return repository.findClient();
}
#ServiceActivator(inputChannel="sendClientMailChannel")
public void sendToClient(Client payload) {
service.sendClientMail(payload);
}
#Bean
public DirectChannel sendClientMailChannel() {
return new DirectChannel();
}
note: I didn't have to ref the property file.
I need to read java properties file inside my Spring MVC app but I can't find the way to do that. I tried several answers from similar question here on SO, but I was unsuccessful. I'm new to Java, and especially Spring MVC so I probably messed up something.
I'm not sure anymore that the file is being successfully deployed. I'm using Tomcat btw.
If you are using Spring 3.1+ you can use the #PropertySource annotation:
#Configuration
#PropertySource("classpath:/com/example/app.properties")
public class AppConfig {
// create beans
}
or for XML-based configuration you can use the <context:property-placeholder>:
<beans>
<context:property-placeholder location="classpath:com/example/app.properties"/>
<!-- bean declarations -->
</beans>
then you can autowire the key in the properties file using the #Value annotation:
#Value("${property.key}") String propertyValue;
Read more details in the Spring reference docs.
You can have properties files automatically loaded in Spring by using the PropertySourcesPlaceholderConfigurer.
Here is an example of configuring a PropertySourcesPlaceholderConfigurer using Spring JavaConfig:
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
PropertySourcesPlaceholderConfigurer props = new PropertySourcesPlaceholderConfigurer();
props.setLocations(new Resource[] {
new ClassPathResource("/config/myconfig.properties"),
new ClassPathResource("version.properties")
});
}
This will load the properties from the files above on the classpath.
You can use these properties in property replacements within your application. For example, assume that there is a property in one of those files above named myprop. You could inject myprop's value into a field using the following:
#Value(${myprop})
private String someProperty;
You can also access the values of the properties by injecting Spring's Environment object into your classes.
#Resource
private Environment environment;
public void doSomething() {
String myPropValue = environment.getProperty("myprop");
}
In order to read any old file from within a web application the link that Frederic posted in the comments above provides a good explanation of the normal classloader hurdles one encounters when attempting to read files from within their war file and the solutions around it.
You can try the below code.
Add this to servelt-context.xml
<context:property-placeholder location="classpath:config.properties"/>
And to access the contents of config file in java,
#Value("${KEY}")
private String value;
Having this class to override an already set #PropertySource in another Config class.
#Configuration
#PropertySource({ "classpath:${env.placeholder}/app.properties" })
public class PropertyOverrideConfig {
}
But whenever the file or placeholder is missing, its failing the context loading. I need to set the following flags to that annotation loaded property, so that it will skip, if its not able to find the property.
setIgnoreResourceNotFound(true);
setIgnoreUnresolvablePlaceholders(true);
Question1: What would be the appropriate way to set these flags for the #PropertySource?
Updates:
Tried adding a #Bean to the same class without that annotation referring this page, it ain't picking the property file either. I don't have an xml configuration.
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
final PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
Resource[] resources = new ClassPathResource[ ] {
new ClassPathResource( "classpath:${env.placeholder}/app.properties" ) };
pspc.setLocations( resources );
pspc.setIgnoreResourceNotFound(true);
pspc.setIgnoreUnresolvablePlaceholders(true);
return pspc;
}
Question2: I am sure I'm missing something, but couldn't figure out what it is, any help would be great.
I think I finally figured out the answer for the Question1:
How to set Ignore flags for properties added through #PropertySource?
Its not there in Spring still, its been proposed as an Minor
Improvement. Hopefully will be able to see an additional attribute
added to the annotation soon in future release.
SPR-8371
Still not sure about the way to accomplish the scenario mentioned and no answer for Question2.
Not really a solution, but a workaround, if you have to stick to Spring 3: use a dummy default, which exists, i.e. in your case:
#PropertySource({ "classpath:${env.placeholder:dummy}/app.properties" })
Try removing classpath:, it is not needed when using ClassPathResource:
new ClassPathResource( "classpath:${env.placeholder}/app.properties" ) };
I am trying to use #Value annotation in the parameters of a constructor as follows:
#Autowired
public StringEncryptor(
#Value("${encryptor.password:\"\"}") String password,
#Value("${encryptor.algorithm:\"PBEWithMD5AndTripleDES\"}") String algorithm,
#Value("${encryptor.poolSize:10}") Integer poolSize,
#Value("${encryptor.salt:\"\"}") String salt) {
...
}
When the properties file is present on the classpath, the properties are loaded perfectly and the test executes fine. However when I remove the properties file from the classpath, I would have expected that the default values would have been used, for example poolSize would be set to 10 or algorithm to PBEWithMD5AndTripleDES however this is not the case.
Running the code through a debugger (which would only work after changing #Value("${encryptor.poolSize:10}") Integer poolSize to #Value("${encryptor.poolSize:10}") String poolSize as it was causing NumberFormatExceptions) I find that the defaults are not being set and the parameters are in the form of:
poolSize = ${encryptor.poolSize:10} or
algorithm = ${encryptor.algorithm:"PBEWithMD5AndTripleDES"}
rather than the expected
poolSize = 10 or
algorithm = "PBEWithMD5AndTripleDES"
Based on SPR-4785 the notation such as ${my.property:myDefaultValue} should work. Yet it's not happening for me!
Thank you
Perhaps initialization of property placeholder configurer fails due to missed properties file, so that placeholders are not resolved. You can configure it to ignore missed files as follows (if you use context namespace to configure it):
<context:property-placeholder ignore-resource-not-found="true" ... />
Also you don't need "..." around default values.
ignore-resource-not-found="true" is not necessary for the defaults to be picked up. The point of specifying the default value is for it to be used if the property is not found anywhere.
I think the last sentence in the previous answer points to the problem - incorrect EL that you must have originally provided but then removed from the example. The fact that you were getting format conversion exceptions points to that as well. Normally, Spring will automatically convert Strings to the appropriate "standard" Java type, and if you provide your own implementation of the Spring Conversion Service, to your custom objects as well - as long as your conversion service is defined in the app context.
"ignore-resource-not-found" is useful when you are injecting properties via XML without defaults and don't want the container to throw an exception instantiating the bean in case no property is found. In such cases the bean properties will be initialized with the Java defaults, e.g. nulls fro objects, 0s for primitive numeric values, etc.
In my case, resolving the property values (and the defaults) did not work in test, where I use an annotation based configuration. It turned out that I had to add a PropertySourcesPlaceholderConfigurer so that properties actually get resolved. It was explained in the PropertySource Annotation JavaDoc:
In order to resolve ${...} placeholders in definitions or #Value annotations using properties from a PropertySource, one must register a PropertySourcesPlaceholderConfigurer. This happens automatically when using in XML, but must be explicitly registered using a static #Bean method when using #Configuration classes. See the "Working with externalized values" section of #Configuration Javadoc and "a note on BeanFactoryPostProcessor-returning #Bean methods" of #Bean Javadoc for details and examples.
The following did the trick:
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
And if you want to add individual properties:
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
Properties properties = new Properties();
properties.put("batchSize", "250");
propertySourcesPlaceholderConfigurer.setProperties(properties);
return propertySourcesPlaceholderConfigurer;
}