Skip to content

Commit 275bb8e

Browse files
committed
DATACMNS-485 - Fixed false negative type alias detection in MappingContextTypeInformationMapper.
MappingContextTypeInformationMapper now considers the raw type only for type alias conflict detection.
1 parent 02046da commit 275bb8e

File tree

2 files changed

+58
-3
lines changed

2 files changed

+58
-3
lines changed

src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.springframework.data.mapping.PersistentEntity;
2323
import org.springframework.data.mapping.context.MappingContext;
24+
import org.springframework.data.util.ClassTypeInformation;
2425
import org.springframework.data.util.TypeInformation;
2526
import org.springframework.util.Assert;
2627

@@ -90,12 +91,31 @@ private void safelyAddToCache(TypeInformation<?> key, Object alias) {
9091
return;
9192
}
9293

93-
if (typeMap.containsValue(alias)) {
94+
TypeInformation<?> toStore = ClassTypeInformation.from(key.getType());
95+
Object existingAlias = typeMap.get(toStore);
96+
97+
// Reject second alias for same type
98+
99+
if (existingAlias != null && !alias.equals(existingAlias)) {
94100
throw new IllegalArgumentException(String.format(
95-
"Detected mapping ambiguity! String %s cannot be mapped to more than one type!", alias));
101+
"Trying to register alias '%s', but found already registered alias '%s' for type %s!", alias, existingAlias,
102+
toStore));
103+
}
104+
105+
// Reject second type for same alias
106+
107+
if (typeMap.containsValue(alias)) {
108+
109+
for (Entry<TypeInformation<?>, Object> entry : typeMap.entrySet()) {
110+
if (entry.getValue().equals(alias) && !entry.getKey().equals(toStore)) {
111+
throw new IllegalArgumentException(String.format(
112+
"Detected existing type mapping of %s to alias '%s' but attempted to bind the same alias to %s!",
113+
toStore, alias, entry.getKey()));
114+
}
115+
}
96116
}
97117

98-
typeMap.put(key, alias);
118+
typeMap.put(toStore, alias);
99119
}
100120

101121
/*

src/test/java/org/springframework/data/convert/MappingContextTypeInformationMapperUnitTests.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
import static org.junit.Assert.*;
2020
import static org.springframework.data.util.ClassTypeInformation.*;
2121

22+
import java.util.Arrays;
2223
import java.util.Collections;
24+
import java.util.HashSet;
2325

2426
import org.junit.Before;
2527
import org.junit.Test;
@@ -98,8 +100,41 @@ public void detectsTypeForUnknownEntity() {
98100
assertThat(mapper.resolveTypeFrom("foo"), is((TypeInformation) from(Entity.class)));
99101
}
100102

103+
/**
104+
* @see DATACMNS-485
105+
*/
106+
@Test
107+
@SuppressWarnings("unchecked")
108+
public void createsTypeMapperForGenericTypesWithDifferentBindings() {
109+
110+
SampleMappingContext context = new SampleMappingContext();
111+
context.setInitialEntitySet(new HashSet<Class<? extends Object>>(Arrays.asList(Entity.class, GenericType.class,
112+
ConcreteWrapper.class, GenericWrapper.class)));
113+
context.initialize();
114+
115+
new MappingContextTypeInformationMapper(context);
116+
}
117+
101118
@TypeAlias("foo")
102119
static class Entity {
103120

104121
}
122+
123+
@TypeAlias("genericType")
124+
static class GenericType<T> {
125+
126+
}
127+
128+
@TypeAlias("concreteWrapper")
129+
static class ConcreteWrapper {
130+
131+
GenericType<String> stringGeneric;
132+
GenericType<Integer> integerGeneric;
133+
}
134+
135+
@TypeAlias("genericWrapper")
136+
static class GenericWrapper<T> {
137+
138+
GenericType<T> genericGeneric;
139+
}
105140
}

0 commit comments

Comments
 (0)