Skip to content

Constructor binding of EnumMap fails due to missing key type #41550

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
ciscoo opened this issue Jul 17, 2024 · 2 comments
Closed

Constructor binding of EnumMap fails due to missing key type #41550

ciscoo opened this issue Jul 17, 2024 · 2 comments
Assignees
Labels
type: bug A general bug
Milestone

Comments

@ciscoo
Copy link

ciscoo commented Jul 17, 2024

Given the following:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

import java.util.EnumMap;
import java.util.List;

@EnableConfigurationProperties(DemoApplication.ExampleProperties.class)
@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

	public enum Example {
		ONE, TWO, THREE;
	}

	@ConfigurationProperties(prefix = "example")
	record ExampleProperties(List<ExampleEntry> entries) {}

	record ExampleEntry(String name, EnumMap<Example, String> map) {}
}

and configuration:

example:
  entries:
    - name: one
      map:
        ONE: one
        TWO: two
        THREE: three

Will result in the following exception:

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'example.entries[0].map' to java.util.EnumMap<com.example.demo.DemoApplication$Example, java.lang.String>:

    Property: example.entries[0].name
    Value: "one"
    Origin: class path resource [application.yml] - 3:13
    Reason: java.lang.IllegalArgumentException: Cannot create EnumMap for unknown key type

Action:

Update your application's configuration

It works if I switch to Map instead of EnumMap:

- public record ExampleEntry(String name, EnumMap<Example, String> map) {}
+ public record ExampleEntry(String name, Map<Example, String> map) {}

But the keys (for my use case) are enums and it makes sense to use the specialized map implementation.

After some debugging, it looks to be an issue on Boot's side in ValueObjectBinder:

The key portion is lost which then fails Framework's check:

https://github.com/spring-projects/spring-framework/blob/5715b2a783b383c7cae214c2e37efb43f48d924f/spring-core/src/main/java/org/springframework/core/CollectionFactory.java#L319

Additionally, maybe related: #19156

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 17, 2024
@ciscoo ciscoo changed the title Unable to bind properties to EnumMap due to unknown key type Unable to bind properties to EnumMap due to missing key type Jul 18, 2024
@ciscoo
Copy link
Author

ciscoo commented Jul 18, 2024

Simplified example ExampleProperties to a record.

@wilkinsona wilkinsona changed the title Unable to bind properties to EnumMap due to missing key type Constructor binding of EnumMap fails due to missing key type Jul 18, 2024
@wilkinsona wilkinsona added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Jul 18, 2024
@wilkinsona wilkinsona added this to the 3.2.x milestone Jul 18, 2024
@wilkinsona
Copy link
Member

Thanks for the report. There are two similar problems here. One's in ValueObjectBinder to which you've linked, but it will only occur if the EnumMap record component or constructor parameter is annotated with @DefaultValue. The other is in MapBinder.bindAggregate(ConfigurationPropertyName, Bindable<?>, AggregateElementBinder). I think it's the latter that's causing the failure in your case. Regardless, both need to be updated to handle an EnumMap by providing the key type to CollectionFactory.

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

No branches or pull requests

3 participants