graphql-java-annotations icon indicating copy to clipboard operation
graphql-java-annotations copied to clipboard

Allow Java classes for defining GraphQL interfaces

Open devopsix opened this issue 3 years ago • 0 comments

This is feature request for allowing Java classes – not only interfaces – for defining GraphQL interfaces.

For instance, like this:

@GraphQLInterface
public abstract class MyInterface {
  @GraphQLField
  public String field;
}

This style of defining GraphQL interfaces would allow for more comprehensive code.

Reasoning

Given the Character interface and the Human and Droid types as used throughout the Introduction to GraphQL:

interface Character {
  name: String
  friends: [Character]
}

type Human implements Character {
  name: String
  friends: [Character]
}

type Droid implements Character {
  name: String
  friends: [Character]
}

In order to define this schema with GraphQL-Java Annotations, I would create one Java interface and two Java classes:

@GraphQLTypeResolver(CharacterTypeResolver.class)
public interface Character {
  @GraphQLField
  String getName();
  @GraphQLField
  Set<Character> getFriends();
}

public class Human implements Character {
  private String name;
  private Set<Character> friends;
  @GraphQLField
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
  @GraphQLField
  public Set<Character> getFriends() { return friends; }
  public void setFriends(Set<Character> friends) { this.friends = friends; }
}

public class Droid implements Character {
  private String name;
  private Set<Character> friends;
  @GraphQLField
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
  @GraphQLField
  public Set<Character> getFriends() { return friends; }
  public void setFriends(Set<Character> friends) { this.friends = friends; }
}

In order to avoid duplicate code and to make the classes a better fit for use as JPA entities, I would add an abstract class:

@GraphQLTypeResolver(CharacterTypeResolver.class)
public interface Character {
  @GraphQLField
  String getName();
  @GraphQLField
  Set<Character> getFriends();
}

public abstract class AbstractCharacter implements Character {
  private String name;
  private Set<Character> friends;
  @GraphQLField
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
  @GraphQLField
  public Set<Character> getFriends() { return friends; }
  public void setFriends(Set<Character> friends) { this.friends = friends; }
}

public class Human extends AbstractCharacter implements Character {
}

public class Droid extends AbstractCharacter implements Character {
}

Both AbstractCharacter implements Character and Droid/Human extends AbstractCharacter implements Character are required in order to satisfy the needs of GraphQL-Java Annotations and JPA.

If defining GraphQL interfaces woule be possible as requested the code could be simplified like this:

@GraphQLInterface
@GraphQLTypeResolver(CharacterTypeResolver.class)
public abstract class Character {
  private String name;
  private Set<Character> friends;
  @GraphQLField
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
  @GraphQLField
  public Set<Character> getFriends() { return friends; }
  public void setFriends(Set<Character> friends) { this.friends = friends; }
}

public class Human extends Character {
}

public class Droid extends Character {
}

devopsix avatar Dec 31 '20 16:12 devopsix