.yml file
cassandra:
keyspaceApp:junit
solr:
keyspaceApp:xyz
Bean
@Component
@ConfigurationProperties(prefix="cassandra")
public class CassandraClientNew {
@Value("${keyspaceApp:@null}") private String keyspaceApp;
Main method file
@EnableAutoConfiguration
@ComponentScan
@PropertySource("application.yml")
public class CommonDataApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(CommonDataApplication.class)
.web(false).headless(true).main(CommonDataApplication.class).run(args);
}
}
TestCase
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = CommonDataApplication.class)
@IntegrationTest
@EnableConfigurationProperties
public class CassandraClientTest {
@Autowired
CassandraClientNew cassandraClientNew;
@Test
public void test(){
cassandraClientNew.getSession();
System.out.println(" **** done ****");
}
}
Instead of setting junit as the keyspaceApp it sets xyz.
Looks like prefix="cassandra" not working
It looks like you are trying to use Spring Boot Typesafe Configuration Properties feature.
So in order to have it working correctly, you have to add a few changes to your code:
First of all, your CommonDataApplication
class should have @EnableConfigurationProperties
annotation eg
@EnableAutoConfiguration
@ComponentScan
@PropertySource("application.yml")
@EnableConfigurationProperties
public class CommonDataApplication {
public static void main(String[] args) {
// ...
}
}
I do not believe you need @PropertySource("application.yml")
annotation as application.yml
(as well as application.properties
and application.xml
) is a default configuration file used by Spring Boot.
Your CassandraClientNew
class does not need to have @Value
annotation prefixing keyspaceApp
property. And your keyspaceApp
has to have a setter method .
@Component
@ConfigurationProperties(prefix="cassandra")
public class CassandraClientNew {
private String keyspaceApp;
public void setKeyspaceApp(final String keyspaceApp) {
this.keyspaceApp = keyspaceApp;
}
}
BTW, if you are using List
's or Set
s and you initialise collections (eg List<String> values = new ArrayList<>();
), then only getter is required. If a collection is not initialised then you need to provide a setter method too (otherwise an exception will be thrown).
I hope that will help.
# In application.yaml
a:
b:
c: some_string
@Component
@ConfigurationProperties(prefix = "a", ignoreUnknownFiels = false)
public class MyClassA {
public MyClassB theB; // This name actually does not mean anything
// It can be anything
public void setTheB(MyClassB theB) {
this.theB = theB;
}
public static MyClassB {
public String theC;
public void setTheC(String theC) {
this.theC = theC;
}
}
}
Make sure to have these public methods declared in the above classes. Make sure they have modifier.修饰符。
// In MyClassA
public void setTheB(MyClassB theB) {
this.theB = theB;
}
// In MyClassB
public void setTheC(String theC) {
this.theC = theC;
}
I don't know where the "xyz" came from (maybe you aren't showing your whole application.yml?). You don't normally bind with @Value
in @ConfigurationProperties
though (it has no way of knowing what your prefix is). Did you actually @EnableCongigurationProperties
anywhere? Are you using SpringApplication
to create the application context?
只需从 Lombok 添加一个公共setter或@Setter 。
.yml file
cassandra:
keyspaceApp:junit
solr:
keyspaceApp:xyz
Bean
@Component
@ConfigurationProperties(prefix="cassandra")
public class CassandraClientNew {
@Value("${keyspaceApp:@null}") private String keyspaceApp;
Main method file
@EnableAutoConfiguration
@ComponentScan
@PropertySource("application.yml")
public class CommonDataApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(CommonDataApplication.class)
.web(false).headless(true).main(CommonDataApplication.class).run(args);
}
}
TestCase
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = CommonDataApplication.class)
@IntegrationTest
@EnableConfigurationProperties
public class CassandraClientTest {
@Autowired
CassandraClientNew cassandraClientNew;
@Test
public void test(){
cassandraClientNew.getSession();
System.out.println(" **** done ****");
}
}
Instead of setting junit as the keyspaceApp it sets xyz.
Looks like prefix="cassandra" not working
That's my FULL solution for this case:
My Class will be receiving the properties :
// Setter are CRUCIAL for PropertySource + ConfigurationProperties works properly
@PropertySource(value = "classpath:application-dev.yml", ignoreResourceNotFound = true)
@ConfigurationProperties(prefix = "spring.data.mongodb")
@Setter
@Profile("dev")
@Configuration
@EnableReactiveMongoRepositories(
basePackages = {
"com.webflux.mongo2.project.repo",
"com.webflux.mongo2.task.repo"})
public class MyClassGettingTheProperties {
private String database;
private String host;
private String port;
private String username;
private String password;
private String authenticationDatabase;
}
My property file - application-dev.yml :
spring:
data:
mongodb:
database: ${MONGO_INITDB_DATABASE}
host: ${HOST}
port: ${PORT}
username: ${MONGO_INITDB_ROOT_USERNAME}
password: ${MONGO_INITDB_ROOT_PASSWORD}
authentication-database: ${AUTH_MAN}
My docker-compose which is the "origin" of the properties:
version: "3.4"
x-common-variables:
&env-vars
PORT_API: 1313
MONGO_INITDB_DATABASE: zzzzz
HOST: yyyyy
PORT: 27017
MONGO_INITDB_ROOT_USERNAME: xxxxx
MONGO_INITDB_ROOT_PASSWORD: xxxxxxx
AUTH_MAN: kkkkk
volumes:
api_vol:
networks:
mongo-cluster:
services:
api-db:
container_name: api-db
image: mongo:4.4.4
restart: always
ports:
- "27017:27017"
networks:
- mongo-cluster
volumes:
- api_vol:/data/db
environment:
*env-vars
I had a similar but different issue compared to OP, and couldn't find an answer anywhere, so I'll post about it. Let say you're trying to use Lombok to go and auto generate the getters & setters & other fields for you in your configuration file.
Here is an example:
@Configuration
@ConfigurationProperties(prefix = "address")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AddressConfig {
private Endpoint endpoint;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class Endpoint {
private String url;
}
}
If using lombok @Getter
& @Setter
annotations (or @Data
which also takes care of @Getter
& @Setter
), then make sure to also have this annotation:
@Accessors(fluent = false)
The reason: spring needs the setter methods to actually populate the configuration for you. However, in the above example, here's how the url would be set internally in spring:
addressConfig.getEndpoint().setUrl("...")
;
You can see that getters are prefixed with get
and setters are prefixed with set
.
If you do NOT have @Accessors(fluent = false)
set, then the setters will use the fluent style of accessors, which don't prepend getters with the word get and setters with the word set. This breaks springs ability to populate configuration pojos properly.
Spring will not tell you this when you execute the application. You only get null pointer exceptions when trying when your application tries to use those configuration variables. I only realized I need to put an @Accessors(fluent = false)
annotation after hours of trial & error since I couldn't find the answer on google or stackoverflow. side note: intellij will warn you that false
is the default value for @Accessors
. This is wrong -_-
Anyways, here's the configuration class with the annotation (yes, you only need to add this at the top of the class, just one time, and not in the inner classes).
@Configuration
@ConfigurationProperties(prefix = "address")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class AddressConfig {
private Endpoint endpoint;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(fluent = false)
@Builder
public static class Endpoint {
private String url;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.