Skip to content

Allow binding to collections when a boolean 'is' method also exists #23007

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
DMarkD opened this issue Aug 19, 2020 · 8 comments
Closed

Allow binding to collections when a boolean 'is' method also exists #23007

DMarkD opened this issue Aug 19, 2020 · 8 comments
Assignees
Labels
type: enhancement A general enhancement
Milestone

Comments

@DMarkD
Copy link

DMarkD commented Aug 19, 2020

Java 11.02
Spring Boot 2.3.3.RELEASE

I am having problem with application.properties file.

application.properties sometimes doesn't gets parsed when using Configuration List POJO. It seams to be some type of race condition. Not all the elements of list are parsed. The more fields I have in POJO the most likely it fail to parse application.properties. Most of the fields are String datatype in POJO

POJO:

public class ExternalRdbConfig {

	private String name;
	private int expirationInSeconds;
	private String driver;
	private String url;
	private String user;
	private String password;

        public ExternalRdbConfig(){}

        // getters, setters...
}

Configuration:

@Configuration
@EnableAutoConfiguration
@ConfigurationProperties(prefix = "external.resource")
public class ExternalConfig {
        private final ArrayList<ExternalRdbConfig> rdb;

         public ExternalConfig() {
		this.rdb = new ArrayList<>();
         }
         
        public List<ExternalRdbConfig> getRdb() {
		return rdb;
	 }
    
         dump() {
         .......
         }
}

Controller

@RestController
public class EdpController {

	@Autowired
	private ExternalConfig externalConfig;

	// Start only after all beans are loaded
	@EventListener(ApplicationReadyEvent.class)
	private void start() throws Exception {
		externalConfig.dump();
	}
}

application.properties

external.resource.rdb[0].name=Name0
external.resource.rdb[0].expirationInSeconds=0
external.resource.rdb[0].driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
external.resource.rdb[0].url=jdbc:sqlserver://10.102.130.197:1433;DatabaseName=R
external.resource.rdb[0].user=sa

external.resource.rdb[1].name=Name1
external.resource.rdb[1].expirationInSeconds=1
external.resource.rdb[1].driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
external.resource.rdb[1].url=jdbc:sqlserver://10.102.130.197:1433;DatabaseName=R
external.resource.rdb[1].user=sa

external.resource.rdb[2].name=Name2
external.resource.rdb[2].expirationInSeconds=2
external.resource.rdb[2].driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
external.resource.rdb[2].url=jdbc:sqlserver://10.102.130.197:1433;DatabaseName=R
external.resource.rdb[2].user=sa

external.resource.rdb[3].name=Name3
external.resource.rdb[3].expirationInSeconds=3
external.resource.rdb[3].driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
external.resource.rdb[3].url=jdbc:sqlserver://10.102.130.197:1433;DatabaseName=R
external.resource.rdb[3].user=sa


external.resource.rdb[4].name=Name4
external.resource.rdb[4].expirationInSeconds=4
external.resource.rdb[4].driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
external.resource.rdb[4].url=jdbc:sqlserver://10.102.130.197:1433;DatabaseName=R
external.resource.rdb[4].user=sa
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 19, 2020
@DMarkD
Copy link
Author

DMarkD commented Aug 19, 2020

I can also reproduce with Spring Boot 2.2.5.RELEASE

@philwebb
Copy link
Member

It's hard to say exactly what's going on, but having a @ConfigurationProperties class also be a @Configuration class is a little unusual. I'd recommend not doing that and keeping them as regular @Component beans.

If that doesn't fix it, please could you provide a small sample application that we can run so that we can debug the problem.

@philwebb philwebb added the status: waiting-for-feedback We need additional information before we can continue label Aug 19, 2020
@DMarkD
Copy link
Author

DMarkD commented Aug 19, 2020

edp2.zip

Changing to @Component did not help. I attached file with project. I am currently using Eclipse Version: 2019-03 (4.11.0). The project is stripped and simplified.

Basically I have 3 different external.resource definitions (jdbc, http, file). Each of this resources is a List[POJO]. When I run the program I only get external.resource.file[xx] parsed. If I remove external.resource.file[xx] from application.properties, then once in a while jdbc[xx] and/or http[xx] gets parsed.

Does Spring Boot support multiple List[POJO] in the same @ConfigurationProperties->prefix?

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Aug 19, 2020
@jnizet
Copy link
Contributor

jnizet commented Aug 19, 2020

I've been able to reproduce the issue with your code.
But reading it, I immediately suspected issues caused by the naming of several of your methods.

For example, you have a method named boolean isFile() in ExternalResourceConfig, which clashes (in terms of Java Bean properties) with the method List<ExternalFileConfig> getFile(). If you rename these isXxx() methods to, for example, hasXxx(), so that Spring doesn't think they're getters for boolean properties, then everything is populated correctly.

@philwebb philwebb changed the title Spring Boot Configuration List<POJO> issue Fail bind if ambigous get/is combination is found Aug 19, 2020
@philwebb
Copy link
Member

Thanks @jnizet, that is indeed the problem. The combination of String<List> get... and boolean is... confuses the binder into sometimes trying to bind a list, and sometimes a boolean.

We had a similar issue in the past with setters (see #16206).

I'm going to make this one an enhancement to see if we can provide a better error.

@philwebb philwebb added type: enhancement A general enhancement and removed status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged labels Aug 19, 2020
@philwebb philwebb added this to the 2.4.x milestone Aug 19, 2020
@DMarkD
Copy link
Author

DMarkD commented Aug 20, 2020

By changing to boolean hasXxx() fixed the problem.

@DMarkD DMarkD closed this as completed Aug 20, 2020
@snicoll
Copy link
Member

snicoll commented Aug 20, 2020

@DMarkD, we'd like to enhance the error message as Phil indicated above, please don't close the issue.

@snicoll snicoll reopened this Aug 20, 2020
@philwebb philwebb changed the title Fail bind if ambigous get/is combination is found Allow binding to collections when a boolean 'is' method also exists Sep 21, 2020
@philwebb philwebb self-assigned this Sep 21, 2020
@philwebb
Copy link
Member

I've tweaked the logic so that a get/is combo favors the get. This aligns well with the existing logic we added for #16206.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

5 participants