Skip to content

SchemaMappingInspector field resolution should check public fields to match PropertyFetchingImpl #1101

Closed
@meostyles

Description

@meostyles

To generate the SchemaReport, the SchemaMappingGenerator uses BeanUtils#getPropertyDescriptor, which internally only caches those fields with public getters in the propertyDescriptors collection

@Nullable
PropertyDescriptor getPropertyDescriptor(String name) {
    PropertyDescriptor pd = (PropertyDescriptor)this.propertyDescriptors.get(name);
    if (pd == null && StringUtils.hasLength(name)) {
        pd = (PropertyDescriptor)this.propertyDescriptors.get(StringUtils.uncapitalize(name));
        if (pd == null) {
            pd = (PropertyDescriptor)this.propertyDescriptors.get(StringUtils.capitalize(name));
        }
    }

    return pd;
}

This does not match the PropertyFetchingImpl, which is the default responsible for resolving the field and fetching the data from it

private Object getPropertyViaFieldAccess(CacheKey cacheKey, Object object, String propertyName) throws FastNoSuchMethodException {
    Class<?> aClass = object.getClass();
    try {
        Field field = aClass.getField(propertyName);
        FIELD_CACHE.putIfAbsent(cacheKey, field);
        return field.get(object);
    } catch (NoSuchFieldException e) {
        if (!USE_SET_ACCESSIBLE.get()) {
            throw new FastNoSuchMethodException(cacheKey.toString());
        }
        // if not public fields then try via setAccessible
        try {
            Field field = aClass.getDeclaredField(propertyName);
            field.setAccessible(true);
            FIELD_CACHE.putIfAbsent(cacheKey, field);
            return field.get(object);
        } catch (SecurityException | NoSuchFieldException ignored2) {
            throw new FastNoSuchMethodException(cacheKey.toString());
        } catch (IllegalAccessException e1) {
            throw new GraphQLException(e);
        }
    } catch (IllegalAccessException e) {
        throw new GraphQLException(e);
    }
}

How does this affect us?

We have a number of fields that are public final fields, but do not have public getters. Spring for GraphQL resolves the data, but the schema report warns that the fields are unmapped, which is untrue. We hook into the schema report and throw an exception if there are any unmapped fields by using GraphQlSourceBuilderCustomizer#inspectSchemaMappings. It is important for us to ensure that changes to our data model do not silently break our GraphQL API without us realising.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions