graphql-java-generator / graphql-gradle-plugin-project

graphql-gradle-plugin is a Gradle Plugin for GraphQL, based on graphql-java. It accelerates the development for both the client and the server, by generating the Java code. It allows a quicker development when in contract-first approach, by avoiding to code the boilerplate code.
https://graphql-maven-plugin-project.graphql-java-generator.com/
MIT License
54 stars 8 forks source link

Compiler warnings in generated POJOs #15

Closed steven-sheehy closed 11 months ago

steven-sheehy commented 1 year ago

The server model POJO generation triggers javac compiler warnings when -Xlint:all is passed to the compiler.

build/generated/sources/graphqlGradlePlugin/com/example/graphql/viewmodel/Account.java:519: warning: [cast] redundant cast to Long
                        this.pendingReward = (java.lang.Long) pendingReward;

The generated Java code seems to have a lot of unnecessary checks that can be removed since the setter already defines the exact type:

@Override
public void setPendingReward(java.lang.Long pendingReward) {
    if (pendingReward == null || pendingReward instanceof java.lang.Long) {
        this.pendingReward = (java.lang.Long) pendingReward;
    } else {
        throw new IllegalArgumentException("The given pendingReward should be an instance of java.lang.Long, but is an instance of " + pendingReward.getClass().getName());
    }
}

I think the following would be equivalent:

@Override
public void setPendingReward(java.lang.Long pendingReward) {
    this.pendingReward = pendingReward;
}
etienne-sf commented 1 year ago

That is right. And strange.

I'll dig in my history to find why this code is generated. The sample you provided is quite clear. But there my be other cases where it's useful. And if so, this code should only be generated in theses cases...

etienne-sf commented 1 year ago

Ok, I've checked that.

This control is useless in the case you've shown, of course.

But GraphQL allows things that are difficult to adapt in Java.

Here is a sample:

´´´ interface IP { attr : String! } type TP implements IP { attr : String! } interface I2 { a: IP } type T2 implements I2 { a: TP } ´´´

T2 must implement both ´setA(IP)´ and ´setA(TP)´. So you may call ´setA´ with a class of your own, that implement IP but is not an instance of TP.

But I was perhaps too careful.

I'll check if I can ease a little this control.

Étienne