Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 830 Vote(s) - 3.44 Average
  • 1
  • 2
  • 3
  • 4
  • 5
@ConfigurationProperties prefix not working

#1
.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
Reply

#2
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?
Reply

#3
It looks like you are trying to use Spring Boot [Typesafe Configuration Properties][1] 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 e.g.

@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 (e.g. `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.

[1]:

[To see links please register here]

Reply

#4
# General answer

<!-- language: yaml -->
### 1. In your properties file (application.properties or application.yml)

# In application.yaml
a:
b:
c: some_string

### 2. Declare your class:
<!-- language: java -->

@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;
}

}

}

### 3. Declare public setters! And this is crucial!
Make sure to have these public methods declared in the above classes. Make sure they have <b>"public"</b> modifier.
<!-- language: java -->

// In MyClassA
public void setTheB(MyClassB theB) {
this.theB = theB;
}

// In MyClassB
public void setTheC(String theC) {
this.theC = theC;
}

## That's it.

###Final notes

- The property names in your classes do not mean anything to Spring. It only uses public setters. I declared them public not to declare public getters here. Your properties may have any access modifiers.
- Pay attention to the attribute "ignoreUnknownFields". Its default value is "true". When it is "false" it will throw exception if any of your properties in file "application.yml" was not bound to any class property. It will help you a lot during debugging.

Reply

#5
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
```
Reply

#6
Just add a public **setter** or **@Setter** from Lombok.
Reply

#7
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:

```java
@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).

```java
@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;
}

}
```
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through