Skip to content

Commit d27ac79

Browse files
committed
Back-off in ResultProcessor if the result object is an instance of the target type.
We now do not attempt to convert the object if it is an instance of the declared target type. Closes #2347.
1 parent 7464325 commit d27ac79

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

src/main/java/org/springframework/data/repository/query/ResultProcessor.java

+4
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,10 @@ public ChainingConverter and(final Converter<Object, Object> converter) {
219219

220220
return new ChainingConverter(targetType, source -> {
221221

222+
if (source == null || targetType.isInstance(source)) {
223+
return source;
224+
}
225+
222226
Object intermediate = ChainingConverter.this.convert(source);
223227

224228
return intermediate == null || targetType.isInstance(intermediate) ? intermediate

src/test/java/org/springframework/data/repository/query/ResultProcessorUnitTests.java

+56
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
import static org.mockito.Mockito.*;
2020

2121
import io.reactivex.Flowable;
22+
import lombok.Getter;
2223
import reactor.core.publisher.Flux;
2324
import reactor.core.publisher.Mono;
25+
import reactor.test.StepVerifier;
2426
import rx.Observable;
2527
import rx.Single;
2628

@@ -308,6 +310,37 @@ void supportsFlowableProjections() throws Exception {
308310
assertThat(content.get(0)).isInstanceOf(SampleProjection.class);
309311
}
310312

313+
@Test // GH-2347
314+
void findByListSkipsConversionIfTypeAlreadyMatches() throws Exception {
315+
316+
List<AbstractDto> result = getProcessor("findAllAbstractDtos")
317+
.processResult(Collections.singletonList(new ConcreteDto("Walter", "White")));
318+
319+
assertThat(result.get(0)).isInstanceOf(ConcreteDto.class);
320+
}
321+
322+
@Test // GH-2347
323+
void streamBySkipsConversionIfTypeAlreadyMatches() throws Exception {
324+
325+
Stream<AbstractDto> result = getProcessor("streamAllAbstractDtos")
326+
.processResult(Stream.of(new ConcreteDto("Walter", "White")));
327+
328+
assertThat(result.findFirst().get()).isInstanceOf(ConcreteDto.class);
329+
}
330+
331+
@Test // GH-2347
332+
void findFluxSkipsConversionIfTypeAlreadyMatches() throws Exception {
333+
334+
Flux<AbstractDto> result = getProcessor("findFluxOfAbstractDtos")
335+
.processResult(Flux.just(new ConcreteDto("Walter", "White")));
336+
337+
result.as(StepVerifier::create) //
338+
.consumeNextWith(actual -> {
339+
340+
assertThat(actual).isInstanceOf(ConcreteDto.class);
341+
}).verifyComplete();
342+
}
343+
311344
private static ResultProcessor getProcessor(String methodName, Class<?>... parameters) throws Exception {
312345
return getQueryMethod(methodName, parameters).getResultProcessor();
313346
}
@@ -356,6 +389,12 @@ interface SampleRepository extends Repository<Sample, Long> {
356389
Observable<SampleProjection> findObservableProjection();
357390

358391
Flowable<SampleProjection> findFlowableProjection();
392+
393+
List<AbstractDto> findAllAbstractDtos();
394+
395+
Stream<AbstractDto> streamAllAbstractDtos();
396+
397+
Flux<AbstractDto> findFluxOfAbstractDtos();
359398
}
360399

361400
static class Sample {
@@ -367,6 +406,23 @@ public Sample(String firstname, String lastname) {
367406
}
368407
}
369408

409+
@Getter
410+
static abstract class AbstractDto {
411+
final String firstname, lastname;
412+
413+
public AbstractDto(String firstname, String lastname) {
414+
this.firstname = firstname;
415+
this.lastname = lastname;
416+
}
417+
}
418+
419+
static class ConcreteDto extends AbstractDto {
420+
421+
public ConcreteDto(String firstname, String lastname) {
422+
super(firstname, lastname);
423+
}
424+
}
425+
370426
static class SampleDto {}
371427

372428
@lombok.Value

0 commit comments

Comments
 (0)