-
Notifications
You must be signed in to change notification settings - Fork 41.2k
Binding to a Map with EnumSet values fails with "Cannot create EnumSet for unknown element type" #15539
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
Comments
Thanks for the report, but I can't reproduce the behaviour that you have described. Consider the following application: package com.example.demo;
import java.util.EnumSet;
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;
@SpringBootApplication
@EnableConfigurationProperties(ExampleProperties.class)
public class Gh15539Application {
public static void main(String[] args) {
ExampleProperties properties = SpringApplication.run(Gh15539Application.class,
"--example.directions=north,south").getBean(ExampleProperties.class);
System.out.println(properties.getDirections());
}
}
@ConfigurationProperties("example")
class ExampleProperties {
private EnumSet<Direction> directions;
public EnumSet<Direction> getDirections() {
return directions;
}
public void setDirections(EnumSet<Direction> directions) {
this.directions = directions;
}
}
enum Direction {
NORTH, SOUTH, EAST, WEST
} It produces the following output when run:
If you'd like us to spend some more time investigating, can you please provide a minimal sample (something that we can unzip or git clone) that reproduces the behaviour you have described? |
Thanks for the quick response - here's a recreator for how I'm getting the error. I'm rebinding properties from a YAML file myself using code similar to the following. This for me gives the "Cannot create EnumSet for unknown element type" IllegalArgumentException:
with test.yaml:
|
Thanks for the sample @olideakin. It looks like a bug and this should actually be |
…t for unknown element type" spring-projects#15539
Here's an addition to @Test
public void bindToMapWithEnumSetValuesShouldPopulateMap() {
ResolvableType type = ResolvableType.forClassWithGenerics(Map.class,
ResolvableType.forClass(String.class),
ResolvableType.forClassWithGenerics(EnumSet.class, Direction.class));
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("a.alpha", "north");
source.put("a.bravo", "east");
source.put("a.charlie", "west");
this.sources.add(source);
this.binder.bind("a", Bindable.<Map<String, EnumSet<Direction>>>of(type)).get();
}
static enum Direction {
NORTH, SOUTH, EAST, WEST;
} The following change moves things a bit further along: diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/CollectionBinder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/CollectionBinder.java
index 4213abd7da..99d0582a26 100644
--- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/CollectionBinder.java
+++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/CollectionBinder.java
@@ -46,7 +46,8 @@ class CollectionBinder extends IndexedElementsBinder<Collection<Object>> {
target.getType().asCollection().getGenerics());
ResolvableType elementType = target.getType().asCollection().getGeneric();
IndexedCollectionSupplier result = new IndexedCollectionSupplier(
- () -> CollectionFactory.createCollection(collectionType, 0));
+ () -> CollectionFactory.createCollection(collectionType,
+ elementType.resolve(), 0));
bindIndexed(name, target, elementBinder, aggregateType, elementType, result);
if (result.wasSupplied()) {
return result.get(); However, we then see a failure as Framework tries to create a
I have thus far been unable to find a way to pass sufficient type information into the conversion service so that the collection-to-collection conversion is short-circuited. It looks like we may need a change in Framework here as well. |
Thanks @wilkinsona. It doesn't look like even if were able to pass type information to the |
When binding properties to type EnumSet, there is a failure with "Cannot create EnumSet for unknown element type" as the cause. Stack trace is as follows:
Debugging into the code, it appears this may be caused by a bug.
Stepping into CollectionBinder.bindAggregate(CollectionBinder.java), I can see that aggregateType is set to EnumSet and elementType is set to MyObject, which is expected. However the next lines are:
which does not pass in the elementType.
The next line (bindAggregate) is then invoked which eventually results in a call to the IndexedCollectionSupplier created above, which ends up in CollectionFactory.createCollection():
which of course does not have an elementType set because it was not passed into the earlier call, which then results in the assertion stack trace.
Perhaps the
CollectionFactory.createCollection(collectionType, 0))
should actually beCollectionFactory.createCollection(collectionType, elementType, 0));
?The text was updated successfully, but these errors were encountered: