Skip to content

Commit 82be5d5

Browse files
authored
fix: Description is not inherited from the parent class (#169)
* fix: expose Java feld and read method introspection Api * fix: refactor schema description introspection * fix: polish introspection class names and remove obsolete code * polish * polish formatting * Add test case that validates schema after it is created (#170)
1 parent a5f72bc commit 82be5d5

File tree

6 files changed

+378
-145
lines changed

6 files changed

+378
-145
lines changed

graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/impl/GraphQLJpaSchemaBuilder.java

Lines changed: 38 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,9 @@
1616

1717
package com.introproventures.graphql.jpa.query.schema.impl;
1818

19-
import java.beans.BeanInfo;
20-
import java.beans.IntrospectionException;
21-
import java.beans.Introspector;
22-
import java.beans.PropertyDescriptor;
2319
import java.lang.reflect.AnnotatedElement;
2420
import java.lang.reflect.Field;
2521
import java.lang.reflect.Member;
26-
import java.lang.reflect.Method;
2722
import java.util.ArrayList;
2823
import java.util.Collection;
2924
import java.util.HashMap;
@@ -46,14 +41,13 @@
4641
import org.slf4j.Logger;
4742
import org.slf4j.LoggerFactory;
4843

49-
import com.introproventures.graphql.jpa.query.annotation.GraphQLDescription;
5044
import com.introproventures.graphql.jpa.query.annotation.GraphQLIgnore;
5145
import com.introproventures.graphql.jpa.query.annotation.GraphQLIgnoreFilter;
5246
import com.introproventures.graphql.jpa.query.annotation.GraphQLIgnoreOrder;
5347
import com.introproventures.graphql.jpa.query.schema.GraphQLSchemaBuilder;
5448
import com.introproventures.graphql.jpa.query.schema.JavaScalars;
5549
import com.introproventures.graphql.jpa.query.schema.NamingStrategy;
56-
import com.introproventures.graphql.jpa.query.schema.impl.IntrospectionUtils.CachedIntrospectionResult.CachedPropertyDescriptor;
50+
import com.introproventures.graphql.jpa.query.schema.impl.IntrospectionUtils.EntityIntrospectionResult.AttributePropertyDescriptor;
5751
import com.introproventures.graphql.jpa.query.schema.impl.PredicateFilter.Criteria;
5852

5953
import graphql.Assert;
@@ -164,7 +158,7 @@ private GraphQLObjectType getQueryType() {
164158
private GraphQLFieldDefinition getQueryFieldByIdDefinition(EntityType<?> entityType) {
165159
return GraphQLFieldDefinition.newFieldDefinition()
166160
.name(entityType.getName())
167-
.description(getSchemaDescription( entityType.getJavaType()))
161+
.description(getSchemaDescription(entityType))
168162
.type(getObjectType(entityType))
169163
.dataFetcher(new GraphQLJpaSimpleDataFetcher(entityManager, entityType, toManyDefaultOptional))
170164
.argument(entityType.getAttributes().stream()
@@ -426,7 +420,7 @@ private GraphQLInputObjectField getWhereInputRelationField(Attribute<?,?> attrib
426420
ManagedType<?> foreignType = getForeignType(attribute);
427421

428422
String type = resolveWhereInputTypeName(foreignType);
429-
String description = getSchemaDescription(attribute.getJavaMember());
423+
String description = getSchemaDescription(attribute);
430424

431425
return GraphQLInputObjectField.newInputObjectField()
432426
.name(attribute.getName())
@@ -437,7 +431,7 @@ private GraphQLInputObjectField getWhereInputRelationField(Attribute<?,?> attrib
437431

438432
private GraphQLInputObjectField getWhereInputField(Attribute<?,?> attribute) {
439433
GraphQLInputType type = getWhereAttributeType(attribute);
440-
String description = getSchemaDescription(attribute.getJavaMember());
434+
String description = getSchemaDescription(attribute);
441435

442436
if (type instanceof GraphQLInputType) {
443437
return GraphQLInputObjectField.newInputObjectField()
@@ -599,7 +593,7 @@ else if (attribute.getJavaMember().getClass().isAssignableFrom(Field.class)
599593

600594
private GraphQLArgument getArgument(Attribute<?,?> attribute) {
601595
GraphQLInputType type = getAttributeInputType(attribute);
602-
String description = getSchemaDescription(attribute.getJavaMember());
596+
String description = getSchemaDescription(attribute);
603597

604598
return GraphQLArgument.newArgument()
605599
.name(attribute.getName())
@@ -619,7 +613,7 @@ private GraphQLType getEmbeddableType(EmbeddableType<?> embeddableType, boolean
619613
if (input) {
620614
graphQLType = GraphQLInputObjectType.newInputObject()
621615
.name(embeddableTypeName)
622-
.description(getSchemaDescription(embeddableType.getJavaType()))
616+
.description(getSchemaDescription(embeddableType))
623617
.fields(embeddableType.getAttributes().stream()
624618
.filter(this::isNotIgnored)
625619
.map(this::getInputObjectField)
@@ -629,7 +623,7 @@ private GraphQLType getEmbeddableType(EmbeddableType<?> embeddableType, boolean
629623
} else {
630624
graphQLType = GraphQLObjectType.newObject()
631625
.name(embeddableTypeName)
632-
.description(getSchemaDescription(embeddableType.getJavaType()))
626+
.description(getSchemaDescription(embeddableType))
633627
.fields(embeddableType.getAttributes().stream()
634628
.filter(this::isNotIgnored)
635629
.map(this::getObjectField)
@@ -655,7 +649,7 @@ private GraphQLObjectType getObjectType(EntityType<?> entityType) {
655649
private GraphQLObjectType computeObjectType(EntityType<?> entityType) {
656650
return GraphQLObjectType.newObject()
657651
.name(entityType.getName())
658-
.description(getSchemaDescription(entityType.getJavaType()))
652+
.description(getSchemaDescription(entityType))
659653
.fields(getEntityAttributesFields(entityType))
660654
.fields(getTransientFields(entityType.getJavaType()))
661655
.build();
@@ -673,27 +667,29 @@ private List<GraphQLFieldDefinition> getEntityAttributesFields(EntityType<?> ent
673667
private List<GraphQLFieldDefinition> getTransientFields(Class<?> clazz) {
674668
return IntrospectionUtils.introspect(clazz)
675669
.getPropertyDescriptors().stream()
676-
.filter(it -> IntrospectionUtils.isTransient(clazz, it.getName()))
677-
.filter(it -> !it.isAnnotationPresent(GraphQLIgnore.class))
678-
.map(CachedPropertyDescriptor::getDelegate)
670+
.filter(AttributePropertyDescriptor::isTransient)
671+
.filter(AttributePropertyDescriptor::isNotIgnored)
679672
.map(this::getJavaFieldDefinition)
680673
.collect(Collectors.toList());
681674
}
682675

683676
@SuppressWarnings( { "rawtypes" } )
684-
private GraphQLFieldDefinition getJavaFieldDefinition(PropertyDescriptor propertyDescriptor) {
677+
private GraphQLFieldDefinition getJavaFieldDefinition(AttributePropertyDescriptor propertyDescriptor) {
685678
GraphQLOutputType type = getGraphQLTypeFromJavaType(propertyDescriptor.getPropertyType());
686679
DataFetcher dataFetcher = PropertyDataFetcher.fetching(propertyDescriptor.getName());
680+
681+
String description = propertyDescriptor.getSchemaDescription()
682+
.orElse(null);
687683

688684
return GraphQLFieldDefinition.newFieldDefinition()
689-
.name(propertyDescriptor.getName())
690-
.description(getSchemaDescription(propertyDescriptor.getPropertyType()))
691-
.type(type)
692-
.dataFetcher(dataFetcher)
693-
.build();
685+
.name(propertyDescriptor.getName())
686+
.description(description)
687+
.type(type)
688+
.dataFetcher(dataFetcher)
689+
.build();
694690
}
695691

696-
private GraphQLFieldDefinition getObjectField(Attribute attribute) {
692+
private GraphQLFieldDefinition getObjectField(Attribute<?,?> attribute) {
697693
return getObjectField(attribute, null);
698694
}
699695

@@ -751,7 +747,7 @@ else if (attribute instanceof PluralAttribute
751747

752748
return GraphQLFieldDefinition.newFieldDefinition()
753749
.name(attribute.getName())
754-
.description(getSchemaDescription(attribute.getJavaMember()))
750+
.description(getSchemaDescription(attribute))
755751
.type(type)
756752
.dataFetcher(dataFetcher)
757753
.argument(arguments)
@@ -780,7 +776,7 @@ private GraphQLInputObjectField getInputObjectField(Attribute attribute) {
780776

781777
return GraphQLInputObjectField.newInputObjectField()
782778
.name(attribute.getName())
783-
.description(getSchemaDescription(attribute.getJavaMember()))
779+
.description(getSchemaDescription(attribute))
784780
.type(type)
785781
.build();
786782
}
@@ -878,86 +874,27 @@ protected final boolean isValidAssociation(Attribute<?,?> attribute) {
878874
return isOneToMany(attribute) || isToOne(attribute);
879875
}
880876

881-
882-
883-
private String getSchemaDescription(Member member) {
884-
if (member instanceof AnnotatedElement) {
885-
String desc = getSchemaDescription((AnnotatedElement) member);
886-
if (desc != null) {
887-
return(desc);
888-
}
889-
}
890-
891-
//The given Member has no @GraphQLDescription set.
892-
//If the Member is a Method it might be a getter/setter, see if the property it represents
893-
//is annotated with @GraphQLDescription
894-
//Alternatively if the Member is a Field its getter might be annotated, see if its getter
895-
//is annotated with @GraphQLDescription
896-
if (member instanceof Method) {
897-
Field fieldMember = getFieldByAccessor((Method)member);
898-
if (fieldMember != null) {
899-
return(getSchemaDescription((AnnotatedElement) fieldMember));
900-
}
901-
} else if (member instanceof Field) {
902-
Method fieldGetter = getGetterOfField((Field)member);
903-
if (fieldGetter != null) {
904-
return(getSchemaDescription((AnnotatedElement) fieldGetter));
905-
}
906-
}
907877

908-
return null;
878+
private String getSchemaDescription(Attribute<?,?> attribute) {
879+
return IntrospectionUtils.introspect(attribute.getDeclaringType()
880+
.getJavaType())
881+
.getPropertyDescriptor(attribute)
882+
.flatMap(AttributePropertyDescriptor::getSchemaDescription)
883+
.orElse(null);
909884
}
910-
911-
private Method getGetterOfField(Field field) {
912-
try {
913-
Class<?> clazz = field.getDeclaringClass();
914-
BeanInfo info = Introspector.getBeanInfo(clazz);
915-
PropertyDescriptor[] props = info.getPropertyDescriptors();
916-
for (PropertyDescriptor pd : props) {
917-
if (pd.getName().equals(field.getName())) {
918-
return(pd.getReadMethod());
919-
}
920-
}
921-
} catch (IntrospectionException e) {
922-
e.printStackTrace();
923-
}
924-
925-
return(null);
926-
}
927-
928-
//from https://stackoverflow.com/questions/13192734/getting-a-property-field-name-using-getter-method-of-a-pojo-java-bean/13514566
929-
private static Field getFieldByAccessor(Method method) {
930-
try {
931-
Class<?> clazz = method.getDeclaringClass();
932-
BeanInfo info = Introspector.getBeanInfo(clazz);
933-
PropertyDescriptor[] props = info.getPropertyDescriptors();
934-
for (PropertyDescriptor pd : props) {
935-
if(method.equals(pd.getWriteMethod()) || method.equals(pd.getReadMethod())) {
936-
String fieldName = pd.getName();
937-
try {
938-
return(clazz.getDeclaredField(fieldName));
939-
} catch (Throwable t) {
940-
log.error("class '" + clazz.getName() + "' contains method '" + method.getName() + "' which is an accessor for a Field named '" + fieldName + "', error getting the field:", t);
941-
return(null);
942-
}
943-
}
944-
}
945-
} catch (Throwable t) {
946-
log.error("error finding Field for accessor with name '" + method.getName() + "'", t);
947-
}
948-
949-
return null;
885+
886+
private String getSchemaDescription(EntityType<?> entityType) {
887+
return IntrospectionUtils.introspect(entityType.getJavaType())
888+
.getSchemaDescription()
889+
.orElse(null);
950890
}
951891

952-
private String getSchemaDescription(AnnotatedElement annotatedElement) {
953-
if (annotatedElement != null) {
954-
GraphQLDescription schemaDocumentation = annotatedElement.getAnnotation(GraphQLDescription.class);
955-
return schemaDocumentation != null ? schemaDocumentation.value() : null;
956-
}
957-
958-
return null;
892+
private String getSchemaDescription(EmbeddableType<?> embeddableType) {
893+
return IntrospectionUtils.introspect(embeddableType.getJavaType())
894+
.getSchemaDescription()
895+
.orElse(null);
959896
}
960-
897+
961898
private boolean isNotIgnored(EmbeddableType<?> attribute) {
962899
return isNotIgnored(attribute.getJavaType());
963900
}

0 commit comments

Comments
 (0)