Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SchemaMappingInspector field resolution should match PropertyFetchingImpl #1101

Open
meostyles opened this issue Dec 16, 2024 · 0 comments
Open
Labels
status: waiting-for-triage An issue we've not yet triaged

Comments

@meostyles
Copy link

meostyles commented Dec 16, 2024

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.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Dec 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage An issue we've not yet triaged
Projects
None yet
Development

No branches or pull requests

2 participants