Code Monkey home page Code Monkey logo

Comments (8)

kaqqao avatar kaqqao commented on May 18, 2024

This is a fairly involved setup, so I'll have to analyze this in more depth, but at the first glance it seems auto discovery would work for you.

Just add implementationAutoDiscovery = true to your @GraphQLInterface, i.e. make it @GraphQLInterface(name = "IAnimal", implementationAutoDiscovery = true). This is enough if the implementations are within the base package (test.graphql.model). If they're not, you can also specify the packages to scan via scanPackages property of @GraphQLInterface.

Does this satisfy your needs or did I misunderstand you?

from graphql-spqr.

kaqqao avatar kaqqao commented on May 18, 2024

Ah. I've just tested your scenario. With implementationAutoDiscovery it still fails but for a different reason: both BatImpl and IBat are discovered and it still doesn't know which one to choose. As a temporary work-around, you can explicitly set the scanPackages and keep the interfaces and the impls in separate packages, because the GraphQLIgnore annotation is not considered in this case.

I'll implement the support for GraphQLIgnore in this context in 0.9.2

Another option is to enable implementationAutoDiscovery but then implement your own TypeResolver and provide it via @GraphQLTypeResolver(CustomTypeResolver.class) on either IAnimal or the impl classes.

from graphql-spqr.

kaqqao avatar kaqqao commented on May 18, 2024

Yet a third option would be to implement your own TypeMapper (extending InterfaceMapper) that will take care of the custom logic of detecting and mapping the correct implementations. This is where I'll add the code to skip the implementations annotated with @GraphQLIgnore .

It was an important design goal to keep graphql-spqr insanely extensible and customizable, so if there's a feature you're missing, the chances are you can easily add it yourself.

from graphql-spqr.

asherrecv avatar asherrecv commented on May 18, 2024

Thanks for your effort! I tried out your second solution and it works. I kept Java-Implementations and Java-Interfaces in separate packages, enabled implementationAutoDiscovery on the IAnimal-GraphQL-Interface and additionally annotated it with @GraphQLTypeResolver(DummyTypeResolver.class) (where DummyTypeResolver.resolveType always returns null) and created the schema as I did before.

Now the only thing that raises a question mark, is that the automatically created _type_-field in the domain objects contains the actual Java-Type (e.g. BatImpl instead of IBat) and not the type defined in the GraphQL domain.

from graphql-spqr.

kaqqao avatar kaqqao commented on May 18, 2024

If you're keeping the interfaces and implementations in separate packages, you don't need the @GraphQLTypeResolver.

And as for the _type_ property, it should always be the concrete type that can be instantiated.
It is only needed in case an interface or an abstract class is used as an input type, because it would be impossible to deserialize it from JSON without the knowledge of the concrete type. So it is basically a hint to the deserializer. The only reason _type_ exists in output types is to help the client know the possible value.
It is safe to use, as the possible values of _type_ are whitelisted at startup, so the client can't attempt to inject an arbitrary class name.

In short, if you're not using interfaces/abstract types as input types, you don't care about the _type_ field.

from graphql-spqr.

pmbdias avatar pmbdias commented on May 18, 2024

I have a problem similar to the one reported in this topic but I could not find a solution.
I have got Java types with SPQR-Annotations the following manner:

@GraphQLInterface(name = "IdentificationIf", implementationAutoDiscovery=true)
public interface IdentificationIf{
	@GraphQLQuery(name = "identification")
	public String getIdentification();	
}
@GraphQLType(name = "IdentificationCPF")
public class IdentificationCPF implements IdentificationIf{	
	private String identification;

	public IdentificationCPF(String identification){
		this.identification = identification;
	}

	@GraphQLQuery(name = "identification")
	public String getIdentification(){
		return this.identification;
	}	

	@GraphQLQuery(name = "type")
	public String getType() {
		return "CPF";
	}
}

@GraphQLType(name = "IdentificationCNPJ")
public class IdentificationCNPJ implements IdentificationIf{	
	private String identification;

	public IdentificationCNPJ(String identification){
		this.identification = identification;
	}

	@GraphQLQuery(name = "identification")
	public String getIdentification(){
		return this.identification;
	}

	@GraphQLQuery(name = "branch")
	public String getBranch() {
		String branch = "";
		if(identification != null) {
			branch = identification.substring(7, 12);
		}
		return branch;
	}	
}

@Service
public class ServiceIdentification {	
	@GraphQLQuery(name = "person")
	public Person getSolicitante() {
		Person solic = new Person();
		solic.setName("José");
		solic.setIdentification(new IdentificationCPF("88888888888"));
		return solic;
	}	

	@GraphQLQuery(name = "identificacaoCPF")
	public IdentificationIf getIdentificacaoCPF() {
		return new IdentificationCPF("12345678912");
	}	

	@GraphQLQuery(name = "identificacaoCNPJ")
	public IdentificationIf getIdentificacaoCNPJ() {
		return new IdentificationCNPJ("12345678912345");
	}	
}

When executing the query the error occurs:

{"query":"{person{name, ... on IdentificationCPF {identification, type}, ... on IdentificationCNPJ {identification, branch}}}"}
{errors=[{message=Validation error of type UnknownType: Unknown type IdentificationCPF, locations=[]}, {message=Validation error of type UnknownType: Unknown type IdentificationCNPJ, locations=[]}]}

I'd like to know how I should proceed to work with complex object queries that have interface type attribute.

Thanks in advance.

from graphql-spqr.

kaqqao avatar kaqqao commented on May 18, 2024

@pmbdias I don't see anything obviously wrong in your code... I'd suggest you place a breakpoint in e.g. GraphQLController and analyze the generated schema. It seems as if the implementation types are not automatically discovered for whatever reason. Maybe even place a breakpoint in InterfaceTypeMapper and what happens when it tries to scan for implementations.

from graphql-spqr.

pmbdias avatar pmbdias commented on May 18, 2024

The difference is that the IdentificationCPF object is a concrete class and in the initial example of the post the ICat object is an interface.
The example has two interface levels, but in my case I only have one interface.
I put the breakpoint in GraphQLController and in the generated schema for the example of "zoo" the GraphQLObjectType is generated for ICat, but in my example the GraphQLObjectType does not generate only the InterfaceType.
e.g schemes:

catteste=GraphQLFieldDefinition{name='catteste', type=GraphQLObjectType{name='ICat', description='', fieldDefinitionsByName=[_type_, name, smart], interfaces=[GraphQLInterfaceType{name='IAnimal', description='', fieldDefinitionsByName=[_type_, name], typeResolver=io.leangen.graphql.generator.DelegatingTypeResolver@3f594bf}]}, arguments=[], dataFetcherFactory=graphql.schema.DataFetcherFactories$$Lambda$19748/431014167@1758940c, description='', deprecationReason='null', definition=null}

identificationCPF=GraphQLFieldDefinition{name='identificationCPF', type=GraphQLInterfaceType{name='IdentificationIf', description='', fieldDefinitionsByName=[_type_, formattedID, identification], typeResolver=io.leangen.graphql.generator.DelegatingTypeResolver@3f594bf}, arguments=[], dataFetcherFactory=graphql.schema.DataFetcherFactories$$Lambda$19748/431014167@33f28f68, description='', deprecationReason='null', definition=null}

from graphql-spqr.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.