I use this library to replace links to AWS parameters to they actual values: https://github.com/NitorCreations/spring-property-aws-ssm-resolver/blob/master/src/main/java/com/nitorcreations/spring/aws/SpringPropertySSMParameterResolver.java
This library uses EnvironmentPostProcessor to substitude parameters. Next, I use the following component to get properties:
#Data
#Component
#ConfigurationProperties(prefix = "activemq.connection")
public class ConnectionProperties {}
This library replaces all spring properties except #ConfigurationProperties and I can't understand why. Is there any priority for processing these beans?
UPD: From the library description:
spring-property-aws-ssm-resolver is a small Spring Boot plugin for resolving AWS SSM Parameters during startup simply by using prefixed regular Spring Boot properties.
Set up your Spring Properties with the {ssmParameter} prefix.
Example application.yml:
my.regular.property: 'Foo'
my.secret.property: '{ssmParameter}/myproject/myapp/mysecret'
During startup, the plugin would look for properties with this prefix and replace the value by looking for a property called /myproject/myapp/mysecret on AWS SSM.
I expect this library will replace all values in #ConfigurationProperties on values from AWS SSM, but it actually don't, it leaves them unchanged. I think the reason is in the initialization order of ConfigurationProperties and EnvironmentPostProcessor.
Related
I have a multi-datasource web application with following technique:
Spring boot 1.5.12
Mybats-Spring-boot-starter 1.3.2
And I prefered Java based configuration. Therefore, I have Datasource1Config.java and Datasource2Config.java.
I defined SqlSessionTemplate respectively, and using MapperScannerConfigure to inject my mapper. Following is for datasource1, and the datasource2 just substitute the number.
#Bean(name = "dataSource1MapperScannerConfigurer")
public MapperScannerConfigurer msc() {
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setSqlSessionFactoryBeanName("dataSource1SqlSessionFactory");
msc.setSqlSessionTemplateBeanName("dataSource1SqlSessionFactory");
msc.setBasePackage("demo.mybatisspring.mapper.ds1");
return msc;
}
And then, the error happend
file [C:\...target\classes\demo\mybatisspring\mapper\ds1\UserMapper.class] required a single bean, but 2 were found:
- dataSource1SqlSessionFactory: defined by method 'sqlSessionFactoryBean' in class path resource [demo/mybatisspring/config/DataSource1Config.class]
- dataSource2SqlSessionFactory: defined by method 'sqlSessionFactoryBean2' in class path resource [demo/mybatisspring/config/DataSource2Config.class]
However, if I inject mappers with #MapperScan as following, everything will work fine. (also worked fine when one using #MapperScan and the other using #Bean MapperScannerConfigurer)
#MapperScan(basePackages = "demo.mybatisspring.mapper.ds1", sqlSessionTemplateRef = "dataSource1SqlSessionFactory")
public class DataSource1Config {...}
#MapperScan(basePackages = "demo.mybatisspring.mapper.ds2", sqlSessionTemplateRef = "dataSource2SqlSessionFactory")
public class DataSource2Config {...}
I've tried to trace with debug mode and search so many articles on internet, still can not get the answer instead. So if anyone can help me?
Thanks for your time.
I think answer is here. https://mybatis.org/spring/mappers.html
Scanning for mappers There is no need to register all your mappers one
by one. Instead, you can let MyBatis-Spring scan your classpath for
them.
There are three different ways to do it:
Using the element. Using the annotation #MapperScan
Using a classic Spring xml file and registering the
MapperScannerConfigurer Both and #MapperScan are
features introduced in MyBatis-Spring 1.2.0. #MapperScan requires
Spring 3.1+.
Since 2.0.2, mapper scanning feature support a option
(lazy-initialization) that control lazy initialization
enabled/disabled of mapper bean. The motivation for adding this option
is supporting a lazy initialization control feature supported by
Spring Boot 2.2. The default of this option is false (= not use lazy
initialization). If developer want to use lazy initialization for
mapper bean, it should be set to the true expressly.
I developped a Spring Boot application. This application can be deployed to a test or prod environment, the application is using REST API for making requests. I use POJOs as wrapper, with the JsonProperty annotations containing the field IDs for the API, that it is being pushed to.
ie
#JsonProperty("field_001)
private String name;
#JsonProperty("field_002)
private String address;
The field labels for these values differ on the test endpoint. So the test endpoint might expect the properties to map as
#JsonProperty("field_005)
private String name;
#JsonProperty("field_006)
private String address;
I would like to be able to utilize the Spring Boot native support for profile based properties files. To read in the JsonProperty annotation values at run time from an external properties file.
So for example,
There might be three files application.properties, application-test.properties and application-prod.properties. Spring Boot could read in the test or prod properties in addition to the vanilla properties file based on the "spring.profiles.active" setting.
...-test.properties would contain the constant values for the test server fields. And ...-prod.properties would contain the constant values for the prod server fields.
Nesting annotations such as Spring's #Value tag, like this:
#JsonProperty(#Value("${property.file.reference.here}))
doesn't seem to work.
Best regards
#JsonProperty(#Value("${property.file.reference.here})) won't work simply because :
#JsonProperty uses a String as value, but #Value is an 'Annotation', so that's not a String value, writing it will give you the following error :
Error:(34, 12) java: annotation not valid for an element of type java.lang.String
Plus, #Value will be loaded "once" when spring context loaded.
Edit
If you wish to use test/dev and prod properties, better create a properties file under your test resources package, they will be loaded automatically. (i'm using it that way).
There is actually another approach, is to modify the annotation value at runtime.
How can I set the name of an embedded database started in a Spring Boot app running in a test?
I'm starting two instances of the same Spring Boot app as part of a test, as they collaborate. They are both correctly starting an HSQL database, but defaulting to a database name of testdb despite being provided different values for spring.datasource.name.
How can I provide different database names, or some other means of isolating the two databases? What is going to be the 'lightest touch'? If I can avoid it, I'd rather control this with properties than adding beans to my test config - the test config classes shouldn't be cluttered up because of this one coarse-grained collaboration test.
Gah - setting spring.datasource.name changes the name of the datasource, but not the name of the database.
Setting spring.datasource.url=jdbc:hsql:mem:mydbname does exactly what I need it to. It's a bit crap that I have to hardcode the embedded database implementation, but Spring Boot is using an enum for default values, which would mean a bigger rewrite if it were to try getting the name from a property.
You can try it so:
spring.datasource1.name=testdb
spring.datasource2.name=otherdb
And then declare datasource in your ApplicationConfig like this
#Bean
#ConfigurationProperties(prefix="spring.datasource1")
public DataSource dataSource1() {
...
}
#Bean
#ConfigurationProperties(prefix="spring.datasource2")
public DataSource dataSource2() {
...
}
See official docs for more details: https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html#howto-configure-a-datasource
I have to integrate a list in a YAML config file in Spring Boot, and don't see how to proceed.
I already saw other questions related : Spring Boot yaml configuration for a list of strings
And have the same issue.
I applied the solution and worked around, and found the solution a little tricky.
Is there a way to make lists work with the #Value ?
And if not now, is it expected in future ?
Thanks a lot.
According to this documentation you can do a list in yaml.
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-yaml
YAML lists are represented as property keys with [index] dereferencers, for example this YAML:
my:
servers:
- dev.bar.com
- foo.bar.com
Would be transformed into these properties:
my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com
To bind to properties like that using the Spring DataBinder utilities (which is what #ConfigurationProperties does) you need to have a property in the target bean of type java.util.List (or Set) and you either need to provide a setter, or initialize it with a mutable value, e.g. this will bind to the properties above
#ConfigurationProperties(prefix="my")
public class Config {
private List<String> servers = new ArrayList<String>();
public List<String> getServers() {
return this.servers;
}
}
https://www.youtube.com/watch?v=d6Scea1JdMg&t=9s
Please refer to the above link. Maybe it helps, shown how to read different data types in application.yml in the Spring Boot.
There is a related GitHub thread: #Value annotation should be able to inject List from YAML properties. The issue has been closed, and according to a comment in a duplicate issue, they're not considering implementing the support now. It will be reopened once they decide to work on it.
Until then, you can go the way described in #mark's answer, using #ConfigurationProperties, also mentioned on GitHub.
I need to specify multiple template loader paths for FreeMarker in a Spring Boot web application but the FreeMarkerAutoConfigurationClass only let me specify one path using the spring.freemarker.templateLoaderPath property, which uses the setTemplateLoaderPath method in the FreeMarkerConfigurationFactory. However, this class allows me to set multiple path using the setTemplateLoaderPaths method. Which is the best way to override this auto-configuration class and specify multiple loader paths? I don't really understand well the Spring Java config classes and I want an example for this before write the code I need. I'm using Spring Boot 1.1.2. Thanks in advance.
You'll need to provide your own bean of type org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer with your desired configuration. To do so, add something similar to the following to one of your application's Java configuration classes:
#Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPaths("one", "two", "three");
// Apply further configuration as needed
return configurer;
}
Update: the latest Spring Boot 1.2 snapshots now accept a comma-separated list for the spring.freemarker.templateLoaderPath property allowing you to specify multiple paths without declaring a custom FreeMarkerConfigurer bean.