Polishing in GraphQlArgumentBinder

This commit is contained in:
rstoyanchev
2025-04-17 10:44:44 +01:00
parent 450cef197f
commit 2259a005f8
2 changed files with 25 additions and 23 deletions

View File

@@ -243,8 +243,8 @@ public class GraphQlArgumentBinder {
Constructor<?> constructor = BeanUtils.getResolvableConstructor(targetClass); Constructor<?> constructor = BeanUtils.getResolvableConstructor(targetClass);
Object value = (constructor.getParameterCount() > 0) ? Object value = (constructor.getParameterCount() > 0) ?
bindMapToObjectViaConstructor(rawMap, constructor, targetType, bindingResult) : bindViaConstructorAndSetters(constructor, rawMap, targetType, bindingResult) :
bindMapToObjectViaSetters(rawMap, constructor, targetType, bindingResult); bindViaSetters(constructor, rawMap, targetType, bindingResult);
bindingResult.popNestedPath(); bindingResult.popNestedPath();
@@ -273,9 +273,8 @@ public class GraphQlArgumentBinder {
} }
@Nullable @Nullable
private Object bindMapToObjectViaConstructor( private Object bindViaConstructorAndSetters(Constructor<?> constructor,
Map<String, Object> rawMap, Constructor<?> constructor, ResolvableType ownerType, Map<String, Object> rawMap, ResolvableType ownerType, ArgumentsBindingResult bindingResult) {
ArgumentsBindingResult bindingResult) {
String[] paramNames = BeanUtils.getParameterNames(constructor); String[] paramNames = BeanUtils.getParameterNames(constructor);
Class<?>[] paramTypes = constructor.getParameterTypes(); Class<?>[] paramTypes = constructor.getParameterTypes();
@@ -291,13 +290,9 @@ public class GraphQlArgumentBinder {
name, rawMap.get(name), !rawMap.containsKey(name), targetType, paramTypes[i], bindingResult); name, rawMap.get(name), !rawMap.containsKey(name), targetType, paramTypes[i], bindingResult);
} }
Object target;
try { try {
Object target = BeanUtils.instantiateClass(constructor, constructorArguments); target = BeanUtils.instantiateClass(constructor, constructorArguments);
// only attempt further properties binding if there were no errors
if (!bindingResult.hasErrors()) {
bindProperties(rawMap, ownerType, bindingResult, target);
}
return target;
} }
catch (BeanInstantiationException ex) { catch (BeanInstantiationException ex) {
// Ignore, if we had binding errors to begin with // Ignore, if we had binding errors to begin with
@@ -306,18 +301,26 @@ public class GraphQlArgumentBinder {
} }
throw ex; throw ex;
} }
}
private Object bindMapToObjectViaSetters( // If no errors, apply setters too
Map<String, Object> rawMap, Constructor<?> constructor, ResolvableType ownerType, if (!bindingResult.hasErrors()) {
ArgumentsBindingResult bindingResult) { bindViaSetters(target, rawMap, ownerType, bindingResult);
}
Object target = BeanUtils.instantiateClass(constructor);
bindProperties(rawMap, ownerType, bindingResult, target);
return target; return target;
} }
private void bindProperties(Map<String, Object> rawMap, ResolvableType ownerType, ArgumentsBindingResult bindingResult, Object target) { private Object bindViaSetters(Constructor<?> constructor,
Map<String, Object> rawMap, ResolvableType ownerType, ArgumentsBindingResult bindingResult) {
Object target = BeanUtils.instantiateClass(constructor);
bindViaSetters(target, rawMap, ownerType, bindingResult);
return target;
}
private void bindViaSetters(Object target,
Map<String, Object> rawMap, ResolvableType ownerType, ArgumentsBindingResult bindingResult) {
BeanWrapper beanWrapper = (this.fallBackOnDirectFieldAccess ? BeanWrapper beanWrapper = (this.fallBackOnDirectFieldAccess ?
new DirectFieldAccessFallbackBeanWrapper(target) : PropertyAccessorFactory.forBeanPropertyAccess(target)); new DirectFieldAccessFallbackBeanWrapper(target) : PropertyAccessorFactory.forBeanPropertyAccess(target));
@@ -355,7 +358,6 @@ public class GraphQlArgumentBinder {
} }
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Nullable @Nullable
private <T> T convertValue( private <T> T convertValue(

View File

@@ -195,14 +195,14 @@ class GraphQlArgumentBinderTests {
assertThat(result).hasFieldOrPropertyWithValue("name", "test"); assertThat(result).hasFieldOrPropertyWithValue("name", "test");
} }
@Test @Test // gh-1163
void mixedConstructorProperties() throws Exception { void mixedConstructorProperties() throws Exception {
Object result = bind("{\"name\":\"test\", \"age\":30}", ResolvableType.forClass(MixedConstructorPropertiesBean.class)); Object result = bind("{\"name\":\"test\", \"age\":30}",
ResolvableType.forClass(MixedConstructorPropertiesBean.class));
assertThat(result).isNotNull().isInstanceOf(MixedConstructorPropertiesBean.class); assertThat(result).isNotNull().isInstanceOf(MixedConstructorPropertiesBean.class);
assertThat(result).hasFieldOrPropertyWithValue("name", "test") assertThat(result).hasFieldOrPropertyWithValue("name", "test").hasFieldOrPropertyWithValue("age", 30);
.hasFieldOrPropertyWithValue("age", 30);
} }
@Test @Test