Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom types are not replaced with values from customTypeMapping #1987

Closed
ahar-zz opened this issue Feb 11, 2020 · 16 comments
Closed

Custom types are not replaced with values from customTypeMapping #1987

ahar-zz opened this issue Feb 11, 2020 · 16 comments

Comments

@ahar-zz
Copy link

ahar-zz commented Feb 11, 2020

Summary
I try to use code generation via apollo gradle plugin. CustomType.kt generates, have all CustomType in it, but not get replaced from customTypeMapping values even if I attach adapter.

Description
I use apollo gradle plugin on server application built with spring boot.
I have multiple schema files and multiple queries.

I have configuration in my build.gradle.kts:

apollo {
    generateKotlinModels.set(true)

    service("datocms") {
        sourceFolder.set("$projectDir/src/main/graphql/datocms")
        rootPackageName.set("com.web.bff.queries.datocms")
    }

    service("shopify") {
        sourceFolder.set("$projectDir/src/main/graphql/shopify")
        rootPackageName.set("com.web.bff.queries.shopify")
    }

    service("api") {
        customTypeMapping.put("BigDecimal", "java.math.BigDecimal")

        sourceFolder.set("$projectDir/src/main/graphql/api")
        rootPackageName.set("com.web.bff.queries.api")
        suppressRawTypesWarning.set(true)
    }
}

I put custom adapter for my apolloclient for service "api":

ApolloClient.builder()
        .serverUrl(config.serverUrl)
            .addCustomTypeAdapter(CustomType.BIGDECIMAL, bigDecimalAdapter)
        .okHttpClient(okHttpClient)
        .build()

And I apollo plugin generated the code for CustomType.kt:

enum class CustomType : ScalarType {
  BIGDECIMAL {
    override fun typeName(): String = "BigDecimal"

    override fun javaType(): Class<*> = kotlin.Any::class.java
  },

  ID {
    override fun typeName(): String = "ID"

    override fun javaType(): Class<*> = kotlin.String::class.java
  }
}

As you can see, BigDecimal is kotlin.Any, however in config I said:

customTypeMapping.put("BigDecimal", "java.math.BigDecimal")
However, ID is kotlin.String

Any help is much appreciated.

Version
Plugin version I use is 1.3.0

@sav007
Copy link
Contributor

sav007 commented Feb 12, 2020

@martinbonnin do you think if this issue can be related to the gradle plugin?

@martinbonnin
Copy link
Contributor

martinbonnin commented Feb 12, 2020

@sav007 it could be. I've seen such issues in the past. It was because a gradle MapProperty is empty by default (and not unset). But this was fixed as far as I know

See https://github.com/apollographql/apollo-android/blob/4a3bae8728a42d57a66fbf216d76f95636f8948f/apollo-gradle-plugin/src/main/kotlin/com/apollographql/apollo/gradle/internal/DefaultCompilerParams.kt#L25

I've added a test there: #1991. But it seems to behave as expected.

@ahar, can you try putting the customTypeMapping in the apollo {} block directly ? (Edit: that did not work) Also tell us what version of Gradle are you using ?

@ahar-zz
Copy link
Author

ahar-zz commented Feb 12, 2020

Hello @martinbonnin !
re: try putting the customTypeMapping in the apollo {} block directly
I've tried that before, didn't work. Tried one more time - the same thing.

re: gradle version

------------------------------------------------------------
Gradle 6.0.1
------------------------------------------------------------

Build time:   2019-11-18 20:25:01 UTC
Revision:     fad121066a68c4701acd362daf4287a7c309a0f5

Kotlin:       1.3.50
Groovy:       2.5.8
Ant:          Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM:          11.0.5 (Oracle Corporation 11.0.5+10-LTS)
OS:           Mac OS X 10.14.4 x86_64

By the way, I found there is new version 1.3.1. Updated to 1.3.1 - the same thing.

Thank you for diving in!

@martinbonnin
Copy link
Contributor

martinbonnin commented Feb 12, 2020

Can you try setting customTypeMapping instead of putting values ?

customTypeMapping.set(mapOf("BigDecimal" to "java.math.BigDecimal"))

I would actually expect .put to either work (i.e. initialize the property if unset) or throw (because it is unset) but maybe something else is happening

@ahar-zz
Copy link
Author

ahar-zz commented Feb 12, 2020

@martinbonnin I've tried. Works like a charm.
Thank you for quick response!

@martinbonnin
Copy link
Contributor

That's definitely a weird behaviour. I'll try to dig a bit more see what we can do.

@mos8502
Copy link

mos8502 commented Jul 2, 2020

@martinbonnin Looking at you suggestion of putting customTypeMapping into apollo {} I have come across an issue.
In a single gradle module I have 3 service defined with a single customTypeMapping inside apollo {}and I get the following compilation error: .../type/CustomType.java:12: error: duplicate class: type.CustomType.

I get type.CustomType.java generated three times.

I'm using
gradle: 6.1.1
apollo: 2.2.1
agp: 4.0.0

Is there a way around this?

@martinbonnin
Copy link
Contributor

@mos8502 yep, looks like this putting it in apollo {} directly isn't a good solution.

The solution is to use customTypeMapping.set() instead of customTypeMapping.put():

apollo {
    generateKotlinModels.set(true)

    service("api") {
        customTypeMapping.set(mapOf("BigDecimal" to "java.math.BigDecimal"))

        sourceFolder.set("$projectDir/src/main/graphql/api")
        rootPackageName.set("com.web.bff.queries.api")
        suppressRawTypesWarning.set(true)
    }
}

@mos8502
Copy link

mos8502 commented Jul 2, 2020

@mos8502 yep, looks like this putting it in apollo {} directly isn't a good solution.

The solution is to use customTypeMapping.set() instead of customTypeMapping.put():

apollo {
    generateKotlinModels.set(true)

    service("api") {
        customTypeMapping.set(mapOf("BigDecimal" to "java.math.BigDecimal"))

        sourceFolder.set("$projectDir/src/main/graphql/api")
        rootPackageName.set("com.web.bff.queries.api")
        suppressRawTypesWarning.set(true)
    }
}

@martinbonnin unfortunately even if I define customTypeMapping per service I get the same duplicate class error :(
The generated CustomType will be under type package

@mos8502
Copy link

mos8502 commented Jul 2, 2020

Sorry might have missed to use set instead of put 🤔

@mos8502
Copy link

mos8502 commented Jul 2, 2020

Sorry might have missed to use set instead of put 🤔

@martinbonnin using set whether it is per service or at apollo {} level yields the same result: duplicate class

@martinbonnin
Copy link
Contributor

Can you use different package names for your different services? The layout should look like:

src/main/graphql/service1/net/sample1/schema.json
src/main/graphql/service1/net/sample1/query.graphql
src/main/graphql/service2/net/sample2/schema.json
src/main/graphql/service2/net/sample2/query.graphql
src/main/graphql/service3/net/sample3/schema.json
src/main/graphql/service3/net/sample3/query.graphql

@martinbonnin
Copy link
Contributor

Also it's very unlikely that all your services need the exact same customTypeMapping. Unless they're using the same schema in which case, you're better off using a single service.

@mos8502
Copy link

mos8502 commented Jul 2, 2020

There are three distinct schemas in my case but the customTypeMapping is the same for all. But regardless the issue is that CustomTypes is generated in the same package in a single gradle module

@martinbonnin
Copy link
Contributor

You can control the location of CustomTypes by putting your different schema in different subdirectories, that should generate net.sample1.type.CustomType, net.sample2.type.CustomType, etc... If that's not the case, can you share your directory layout and apollo {} block?

@mos8502
Copy link

mos8502 commented Jul 3, 2020

@martinbonnin the schemas were in different subdirectories, CustomType was regardless generated int the same package for all. The issue was that with the previous version of apollo the code for queries were generated into a package matching the directory structure.

With new version that I'm integrating this doesn't seem to be the case anymore. Adding rootPackageName solves the problem however and all code is generated in the right package.

Thanks for all the help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants