diff --git a/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java b/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java index c5ec1b6d1df7b..a46ffa5f48247 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java @@ -21,6 +21,7 @@ import java.util.HashSet; import java.util.IdentityHashMap; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.ListIterator; import java.util.Map; @@ -29,6 +30,8 @@ import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.stream.Collectors; @@ -1231,12 +1234,16 @@ ResultHandle createValue(MethodContext context, MethodCreator method, ResultHand out = method.newInstance(ofConstructor(param.getClass())); } catch (NoSuchMethodException e) { //fallback for collection types, such as unmodifiableMap - if (expectedType == Map.class) { + if (SortedMap.class.isAssignableFrom(expectedType)) { + out = method.newInstance(ofConstructor(TreeMap.class)); + } else if (Map.class.isAssignableFrom(expectedType)) { out = method.newInstance(ofConstructor(LinkedHashMap.class)); - } else if (expectedType == List.class) { + } else if (List.class.isAssignableFrom(expectedType)) { out = method.newInstance(ofConstructor(ArrayList.class)); - } else if (expectedType == Set.class) { - out = method.newInstance(ofConstructor(Set.class)); + } else if (SortedSet.class.isAssignableFrom(expectedType)) { + out = method.newInstance(ofConstructor(TreeSet.class)); + } else if (Set.class.isAssignableFrom(expectedType)) { + out = method.newInstance(ofConstructor(LinkedHashSet.class)); } else { throw new RuntimeException("Unable to serialize objects of type " + param.getClass() + " to bytecode as it has no default constructor"); diff --git a/core/deployment/src/test/java/io/quarkus/deployment/recording/BytecodeRecorderTestCase.java b/core/deployment/src/test/java/io/quarkus/deployment/recording/BytecodeRecorderTestCase.java index 9a1d3a1ddc0dd..d09e14a6c076e 100644 --- a/core/deployment/src/test/java/io/quarkus/deployment/recording/BytecodeRecorderTestCase.java +++ b/core/deployment/src/test/java/io/quarkus/deployment/recording/BytecodeRecorderTestCase.java @@ -15,7 +15,9 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.function.Consumer; @@ -143,6 +145,40 @@ public void testLargeCollection() throws Exception { }, beans); } + @Test + public void testUnmodifiableMapWithinAMap() throws Exception { + Map> outerMap = new HashMap<>(); + outerMap.put(1, Collections.unmodifiableMap( + Collections.singletonMap(1, new TestJavaBean()))); + + runTest(generator -> { + TestRecorder recorder = generator.getRecordingProxy(TestRecorder.class); + recorder.map(outerMap); + }, outerMap); + } + + @Test + public void testUnmodifiableListWithinAMap() throws Exception { + Map> map = new HashMap<>(); + map.put(1, Collections.unmodifiableList(Collections.singletonList(new TestJavaBean()))); + + runTest(generator -> { + TestRecorder recorder = generator.getRecordingProxy(TestRecorder.class); + recorder.map(map); + }, map); + } + + @Test + public void testUnmodifiableSetWithinAMap() throws Exception { + Map> map = new HashMap<>(); + map.put(1, Collections.unmodifiableSet(Collections.singleton(new TestJavaBean()))); + + runTest(generator -> { + TestRecorder recorder = generator.getRecordingProxy(TestRecorder.class); + recorder.map(map); + }, map); + } + @Test public void testLargeArray() throws Exception {