apollo-kotlin icon indicating copy to clipboard operation
apollo-kotlin copied to clipboard

Java codegen: Add option to generate GraphQL enums as Java enums (opposite of Kotlin `sealedClassesForEnumsMatching`)

Open stengvac opened this issue 2 years ago • 6 comments

Summary Enum declared in graphql schema is generated differently for Java and Kotlin changing with generateKotlinModels.set(false). Is this by design?

Version 3.3.2

Description I would expect enum in schema generated as enum class for Kotlin - done. Also as enum for Java - now enum is generad as class with static fields.

Currently:

public class JobState {
  public static EnumType type = new EnumType("JobState");

  public static JobState RUNNING = new JobState("RUNNING");

  public static JobState SUCCEEDED = new JobState("SUCCEEDED");

  public static JobState FAILED = new JobState("FAILED");

  public String rawValue;
 //rest ommited
}

stengvac avatar Jun 20 '22 16:06 stengvac

Hi 👋

The reason GraphQL enums are mapped to Java classes (and not Java enums) is to allow access to the rawValue that is not known at compile time for new enum values. Imagine your backend introduces a new PAUSED JobState. With a Java enum, the best we can do is map that to an UNKNOWN enum. But that doesn't tell if it's PAUSED or something else.

Now Kotlin has another parameter named sealedClassesForEnumsMatching to opt-in that behaviour but it was never implemented for Java for lack of time. I can see how that's confusing when comparing both codegens. We can certainly add this option when focusing on the Java runtime but there's a lot on the todo list before we can tackle this topic. Feel free to send a pull request though if you're intereseted and we'll look into it!

martinbonnin avatar Jun 20 '22 21:06 martinbonnin

I was mainly curious. For now it is not problem so I can live without it. For now. If it will became required I will create MR for sure. Thx for answer.

stengvac avatar Jun 24 '22 08:06 stengvac

I've updated the title of this issue to make the expected outcome clearer. Let us know if you look into it. If not, we'll tackle this as part of the larger "Java Runtime" effort.

martinbonnin avatar Jun 29 '22 08:06 martinbonnin

Hello, sorry for late response.

I will try to have a look. Will see if I can manage to do it :)

stengvac avatar Jul 04 '22 12:07 stengvac

Thanks 💜

I'd suggest you look into the Kotlin Service.sealedClassesForEnumsMatching. The main difference is that by default it should be listOf(".*") as to not break the current behaviour. Maybe something like this?

  /**
   * A list of [Regex] patterns for GraphQL enums that should be generated as Java classes.
   *
   * Use this if you want your client to have access to the rawValue of the enum. This can be useful if new GraphQL enums are added but
   * the client was compiled against an older schema that doesn't have knowledge of the new enums.
   *
   * Default: listOf(".*")
   */
  val classesForEnumsMatching: ListProperty<String>

martinbonnin avatar Jul 04 '22 13:07 martinbonnin

With #4404 the new option classesForEnumsMatching has been added for this. This will be in the next release, in the meantime it can be tried out with the snapshots.

BoD avatar Sep 20 '22 08:09 BoD

@BoD Is this ok to close? I saw it was closed on the project board.

nateql avatar Oct 27 '22 16:10 nateql

@nateql This is done but has not been released yet - in that case we usually put the "Fixed in SNAPSHOTs" label but keep the issue open, until it's released. It will be part of 3.7.

BoD avatar Oct 27 '22 17:10 BoD

@BoD ok, thank you for the explanation!

nateql avatar Oct 27 '22 17:10 nateql

Available in 3.7.0

BoD avatar Nov 09 '22 08:11 BoD