Skip to content

Commit 9977c61

Browse files
committed
DATACMNS-683 - Tweaked the matching algorithm for DomainClassConverter.
DomainClassConverter as well as its internal ToEntity- and ToIdConverter implementations now actively refrain from matching if the source type is assignable to the target one to prevent unnecessary conversion attempts if the source value already actually is assignable to the target type. Related ticket: DATACMNS-583.
1 parent d48fddf commit 9977c61

File tree

2 files changed

+42
-10
lines changed

2 files changed

+42
-10
lines changed

src/main/java/org/springframework/data/repository/support/DomainClassConverter.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -166,12 +166,12 @@ public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor t
166166
@Override
167167
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
168168

169-
if (!repositories.hasRepositoryFor(targetType.getType())) {
169+
if (sourceType.isAssignableTo(targetType)) {
170170
return false;
171171
}
172172

173-
if (sourceType.equals(targetType)) {
174-
return true;
173+
if (!repositories.hasRepositoryFor(targetType.getType())) {
174+
return false;
175175
}
176176

177177
Class<?> rawIdType = repositories.getRepositoryInformationFor(targetType.getType()).getIdType();
@@ -192,7 +192,7 @@ public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
192192
* @author Oliver Gierke
193193
* @since 1.10
194194
*/
195-
private class ToIdConverter implements ConditionalGenericConverter {
195+
class ToIdConverter implements ConditionalGenericConverter {
196196

197197
/*
198198
* (non-Javadoc)
@@ -232,12 +232,12 @@ public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor t
232232
@Override
233233
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
234234

235-
if (!repositories.hasRepositoryFor(sourceType.getType())) {
235+
if (sourceType.isAssignableTo(targetType)) {
236236
return false;
237237
}
238238

239-
if (sourceType.equals(targetType)) {
240-
return true;
239+
if (!repositories.hasRepositoryFor(sourceType.getType())) {
240+
return false;
241241
}
242242

243243
Class<?> rawIdType = repositories.getRepositoryInformationFor(sourceType.getType()).getIdType();

src/test/java/org/springframework/data/repository/support/DomainClassConverterUnitTests.java

+35-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2014 the original author or authors.
2+
* Copyright 2008-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,6 +20,8 @@
2020
import static org.mockito.Matchers.*;
2121
import static org.mockito.Mockito.*;
2222

23+
import java.lang.reflect.Method;
24+
2325
import org.junit.Before;
2426
import org.junit.Test;
2527
import org.junit.runner.RunWith;
@@ -30,10 +32,14 @@
3032
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
3133
import org.springframework.context.ApplicationContext;
3234
import org.springframework.context.support.GenericApplicationContext;
35+
import org.springframework.core.MethodParameter;
3336
import org.springframework.core.convert.TypeDescriptor;
3437
import org.springframework.core.convert.support.DefaultConversionService;
3538
import org.springframework.data.repository.CrudRepository;
3639
import org.springframework.data.repository.core.support.DummyRepositoryFactoryBean;
40+
import org.springframework.data.repository.support.DomainClassConverter.ToIdConverter;
41+
import org.springframework.test.util.ReflectionTestUtils;
42+
import org.springframework.web.bind.annotation.ModelAttribute;
3743

3844
/**
3945
* Unit test for {@link DomainClassConverter}.
@@ -47,6 +53,7 @@ public class DomainClassConverterUnitTests {
4753
static final User USER = new User();
4854
static final TypeDescriptor STRING_TYPE = TypeDescriptor.valueOf(String.class);
4955
static final TypeDescriptor USER_TYPE = TypeDescriptor.valueOf(User.class);
56+
static final TypeDescriptor SUB_USER_TYPE = TypeDescriptor.valueOf(SubUser.class);
5057
static final TypeDescriptor LONG_TYPE = TypeDescriptor.valueOf(Long.class);
5158

5259
@SuppressWarnings("rawtypes") DomainClassConverter converter;
@@ -144,11 +151,11 @@ public void discoversFactoryAndRepoFromParentApplicationContext() {
144151
* @see DATACMNS-583
145152
*/
146153
@Test
147-
public void shouldReturnSourceObjectIfSourceAndTargetTypesAreTheSame() {
154+
public void converterDoesntMatchIfTargetTypeIsAssignableFromSource() {
148155

149156
converter.setApplicationContext(initContextWithRepo());
150157

151-
assertThat(converter.matches(USER_TYPE, USER_TYPE), is(true));
158+
assertThat(converter.matches(SUB_USER_TYPE, USER_TYPE), is(false));
152159
assertThat((User) converter.convert(USER, USER_TYPE, USER_TYPE), is(USER));
153160
}
154161

@@ -186,6 +193,24 @@ public void supportsConversionFromEntityToString() {
186193
assertThat(converter.matches(USER_TYPE, STRING_TYPE), is(true));
187194
}
188195

196+
/**
197+
* @see DATACMNS-683
198+
*/
199+
@Test
200+
public void toIdConverterDoesNotMatchIfTargetTypeIsAssignableFromSource() throws Exception {
201+
202+
converter.setApplicationContext(initContextWithRepo());
203+
204+
@SuppressWarnings("rawtypes")
205+
DomainClassConverter.ToIdConverter toIdConverter = (ToIdConverter) ReflectionTestUtils.getField(converter,
206+
"toIdConverter");
207+
208+
Method method = Wrapper.class.getMethod("foo", User.class);
209+
TypeDescriptor target = TypeDescriptor.nested(new MethodParameter(method, 0), 0);
210+
211+
assertThat(toIdConverter.matches(SUB_USER_TYPE, target), is(false));
212+
}
213+
189214
private ApplicationContext initContextWithRepo() {
190215

191216
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DummyRepositoryFactoryBean.class);
@@ -199,10 +224,17 @@ private ApplicationContext initContextWithRepo() {
199224
return ctx;
200225
}
201226

227+
static interface Wrapper {
228+
229+
void foo(@ModelAttribute User user);
230+
}
231+
202232
private static class User {
203233

204234
}
205235

236+
private static class SubUser extends User {}
237+
206238
private static interface UserRepository extends CrudRepository<User, Long> {
207239

208240
}

0 commit comments

Comments
 (0)