Ce guide vous aide à diagnostiquer et résoudre les conflits de types courants dans vos schémas GraphQL générés avec GraphQL AutoGen.
Ce type de conflit se produit lorsque deux ou plusieurs classes Java génèrent des types GraphQL avec le même nom.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'graphQLSchema': Type 'User' is already defined
Ce conflit survient lorsqu'un champ est défini plusieurs fois avec des types de retour différents.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'graphQLSchema': Field 'Product.price' has conflicting type definitions: BigDecimal vs Float
Ce conflit se produit lorsque les arguments d'une requête ou d'un champ ont des types incompatibles.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'graphQLSchema': Argument 'id' of field 'Query.product' has conflicting types: ID vs Long
// Dans le package com.example.user
@Entity
@GraphQLType(name = "AppUser") // Renommé pour éviter le conflit
public class User {
// ...
}
// Dans le package com.example.auth
@Entity
@GraphQLType(name = "AuthUser") // Renommé pour éviter le conflit
public class User {
// ...
}
# application.properties
graphql.autogen.use-package-namespaces=true
Avec cette configuration, les types seront automatiquement préfixés avec leur nom de package :
type User_example_user {
id: ID!
username: String!
}
type User_example_auth {
id: ID!
email: String!
}
@GraphQLType
public class Product {
// ...
@GraphQLField(name = "priceAmount")
private BigDecimal price;
// ...
}
@GraphQLType
public class Product {
// ...
@GraphQLIgnore
private BigDecimal price;
@GraphQLField(name = "price")
public Double getPriceAsDouble() {
return price != null ? price.doubleValue() : null;
}
// ...
}
@RestController
public class ProductController {
@GraphQLQuery(name = "product")
public Product getProductById(@GraphQLArgument(name = "id", type = "ID") String id) {
// Conversion en Long si nécessaire
return productService.findById(Long.valueOf(id));
}
}
Pour les applications plus grandes, envisagez de segmenter votre schéma GraphQL par domaines fonctionnels :
# application.properties
graphql.autogen.schemas[0].name=productSchema
graphql.autogen.schemas[0].base-package=com.example.product
graphql.autogen.schemas[0].path=/graphql/product
graphql.autogen.schemas[1].name=userSchema
graphql.autogen.schemas[1].base-package=com.example.user
graphql.autogen.schemas[1].path=/graphql/user
Créez des transformateurs personnalisés pour résoudre les conflits au moment de la génération :
@Component
public class ConflictResolvingTransformer implements GraphQLSchemaTransformer {
@Override
public GraphQLSchema transform(GraphQLSchema originalSchema) {
// Logique personnalisée pour résoudre les conflits
return SchemaTransformer.newSchema(originalSchema)
.renameType("User", "AppUser")
.transformField("Product", "price", field -> field.name("productPrice"))
.build();
}
}
Créez des tests unitaires pour vérifier la validité de votre schéma :
@SpringBootTest
class SchemaValidationTests {
@Autowired
private GraphQLSchema schema;
@Test
void validateSchema() {
SchemaValidator validator = new SchemaValidator();
List errors = validator.validateSchema(schema);
assertThat(errors).isEmpty();
}
@Test
void checkForTypeConflicts() {
// Vérifier spécifiquement les types problématiques connus
assertThat(schema.getType("User")).isNotNull();
assertThat(schema.getType("AppUser")).isNotNull();
}
}