Throw UnsupportedOperationException when a projected value cannot be returned.

We now throw UnsupportedOperationException when a projected value cannot be returned because it cannot be brought into the target type, either via conversion or projection.

This exception improves the error message by avoiding throwing IllegalArgumentException: Projection type must be an interface from the last branch that falls back into projections.

Closes #2290.
Original Pull Request: #2291
This commit is contained in:
Mark Paluch
2021-02-02 16:51:40 +01:00
committed by Christoph Strobl
parent 5e702a8c8a
commit cdeecd4a75
2 changed files with 26 additions and 2 deletions

View File

@@ -104,8 +104,14 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
return projectMapValues((Map<?, ?>) result, type);
} else if (conversionRequiredAndPossible(result, type.getType())) {
return conversionService.convert(result, type.getType());
} else {
} else if (ClassUtils.isAssignable(type.getType(), result.getClass())) {
return result;
} else if (type.getType().isInterface()) {
return getProjection(result, type.getType());
} else {
throw new UnsupportedOperationException(String.format(
"Cannot convert value '%s' of type '%s' to '%s' and cannot create a projection as the target type is not an interface",
result, ClassUtils.getDescriptiveType(result), ClassUtils.getQualifiedName(type.getType())));
}
}
@@ -155,7 +161,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
}
@Nullable
private Object getProjection(Object result, Class<?> returnType) {
private Object getProjection(@Nullable Object result, Class<?> returnType) {
return result == null || ClassUtils.isAssignable(returnType, result.getClass()) ? result
: factory.createProjection(returnType, result);
}