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

Java Runtime

Open martinbonnin opened this issue 2 years ago • 10 comments

Now that apollo-runtime brings kotlinx.coroutines as a dependency, it's not as easy to work with interceptors, etc.. in Java because everything is a Flow or suspend function.

This issue is to gather interest about writing an alternative runtime that can reuse a lot of the common parts (apollo-api, normalization, cache, etc...) but expose a coroutine-free runtime.

  • [ ] #4388
  • [ ] #4389
  • [ ] #4390
  • [ ] #4391
  • [ ] #4393
  • [ ] #4392
  • [ ] #4394
  • [ ] #4395
  • [ ] #4396

martinbonnin avatar Dec 13 '21 16:12 martinbonnin

I would love to see better java support. At least it should be documented how to use the lib with java. I tried yesterday to upgrade to 3.0 but failed.

kicktipp avatar Jan 14 '22 17:01 kicktipp

Same, I'm seeing problems using apollo Optional.Absent and graphql query errors like Type parameter '...Data' is not within its bound; should implement 'com.apollographql.apollo3.api.Operation.Data'.

MatthewFrench avatar Feb 01 '22 05:02 MatthewFrench

Hi @MatthewFrench ! Do you have sample code/a reproducer? Maybe we can fix this one without implementing a separate coroutine-free Java runtime.

martinbonnin avatar Feb 01 '22 08:02 martinbonnin

Hello, I quite advanced in a project in Java and I am trying to use 3.0. Everything is ok until, try to run a query. I couldn't find a single example on how run a query from java, there is this: https://www.apollographql.com/docs/kotlin/advanced/java But examples stop before a query code is demonstrated.

I am pretty new to kotlin so I am a bit lost. Bellow it's image with the things I tried and I am blocked by a similar error as @MatthewFrench All 3 red squiggly lines are this error: Type parameter '...Data' is not within its bound; should implement 'com.apollographql.apollo3.api.Operation.Data'.

Screen Shot 2022-04-01 at 01 17 42

cristian1980 avatar Mar 31 '22 22:03 cristian1980

Hi @cristian1980 👋

Currently the recommended way to use Apollo Kotlin from Java is through the RxJava adapters, which are described here. Basically you would do something like:

Single<ApolloResponse<GetAppConfigQuery.Data>> queryResponse = Rx2Apollo.single(
        apolloClient.query(new GetAppConfigQuery())
);
queryResponse.subscribe( 
        response -> {
          // Use response
        },
        throwable -> {
          // Handle error
        }
);

BoD avatar Apr 01 '22 07:04 BoD

I'm using Rx3Apollo and it works for me in gradle but I get the same error in Intellij:

Screen Shot 2022-05-05 at 6 51 15 PM Screen Shot 2022-05-05 at 6 51 28 PM

Weirdly enough, it works fine when I build on the command line with Gradle, so it's possible something weird is going on in Intellij?

If I manually edit my generated file and change:

public static class Data implements Mutation.Data {

to:

public static class Data implements Mutation.Data, Operation.Data {

... everything works, but I don't know why that would matter since Mutation.Data supposedly already extends Operation.Data.

Screen Shot 2022-05-05 at 6 56 10 PM

I almost never use Java so it's possible I'm missing something obvious here, but wanted to document it in case other people are having this problem too.

brendanlong avatar May 06 '22 00:05 brendanlong

Hi @brendanlong 👋

I don't seem to reproduce the issue on a simple project (with IntelliJ IDEA 2022.1). But seeing that it works on the command line, this would indeed seem to be some kind of issue with IntelliJ.

BoD avatar May 06 '22 09:05 BoD

One possible workaround for people who really need to use Java here, is to create a wrapper class. It requires mixing with Kotlin a little bit.

  1. Create ApolloWrapper.kt, similar to this
fun <D: Query.Data> query(client: ApolloClient,
                          query: Query<D>,
                          listener: QueryApolloResponseListener<D>){
    CoroutineScope(Dispatchers.IO).launch {
        val response = client.query(query).execute()
        response.data?.let {
            listener.onSuccess(it)
        } ?: kotlin.run {
            listener.onFailure(response.errors ?: emptyList())
        }

    }
}

fun <D: Mutation.Data> mutate(client: ApolloClient,
                              mutation: Mutation<D>,
                              listener: MutationApolloResponseListener<D>){
    CoroutineScope(Dispatchers.IO).launch {
        val response = client.mutation(mutation).execute()
        response.data?.let {
            listener.onSuccess(it)
        } ?: kotlin.run {
            listener.onFailure(response.errors ?: emptyList())
        }

    }
}

interface QueryApolloResponseListener<T: Query.Data> {
    fun onSuccess(data: T)
    fun onFailure(error: List<com.apollographql.apollo3.api.Error>)
}

interface MutationApolloResponseListener<T : Mutation.Data> {
    fun onSuccess(data: T)
    fun onFailure(error: List<com.apollographql.apollo3.api.Error>)
}
  1. In your java file, do something like this
public void call(){
        ApolloClient client = new ApolloClient.Builder()
                .serverUrl("https://apollo-fullstack-tutorial.herokuapp.com/graphql")
                .build();
        LoginMutation mutation = new LoginMutation("testEmail");
        ApolloWrapperKt.mutate(client, mutation, new ResponseListener());
    }

    static class ResponseListener implements MutationApolloResponseListener<LoginMutation.Data> {
        @Override
        public void onSuccess(@NonNull LoginMutation.Data data) {
            System.out.println(data);
        }

        @Override
        public void onFailure(@NonNull List<Error> error) {
            System.err.println(error);
        }
    }

So far the compiler haven't complained and I got the response back correctly.

kkunan avatar May 14 '22 05:05 kkunan

Type parameter '...Data' is not within its bound; should implement 'com.apollographql.apollo3.api.Operation.Data'

This probably is not Apollo problem. I have tried some combinations. Kotlin generated classes work fine in Java classes in same gradle module, it seems this is broken when those are made as dependencies and only for IDE - project still compile and is runnable so it is Idea bug?

But in the end yes write generic wrapper public <T extends Mutation.Data> T mutate(Mutation<T> request) { } for those generated classes in java is problematic. Method definition is fine, problem is when called. Then reason: no instance(s) of type variable(s) exist so that Data conforms to Data happens.

stengvac avatar Jun 20 '22 21:06 stengvac

Reported bug to Idea: https://youtrack.jetbrains.com/issue/IDEA-296915

stengvac avatar Jun 28 '22 09:06 stengvac

Hello everyone! Thanks for raising this concern on our support of Java. We appreciate the feedback. 🙏

We are trying to better understand the use of Java with our Kotlin Client, and wanted to ask :

Are any of you using Java for Mobile Android development, or is this something else all together? Any additional information would help us tremendously to better understand your use cases here. Thank you!

jpvajda avatar Oct 21 '22 17:10 jpvajda

We are not using for Android mobile. We are using it as a Java client for a graphql backend. We never used kotlin before.

kicktipp avatar Oct 21 '22 17:10 kicktipp

Hello,

We are using it as client between BE services. Some of them are written in Java and https://youtrack.jetbrains.com/issue/IDEA-296915 make it hard to use generated Kotlin client. Once this issue is gone (should be with Kotlin compiler 1.8) then we can swap to Kotlin.

stengvac avatar Oct 24 '22 13:10 stengvac

@kicktipp and @stengvac thank you for responding!

jpvajda avatar Oct 24 '22 17:10 jpvajda

I have nearly the same use case as @stengvac. IDE support, lack of documentation, and lack of an easy to use java runtime is making the migration to 3.x quite tricky.

maclockard avatar Mar 13 '23 17:03 maclockard

We think that our experimental Java support is feature-complete for the 4.0.0 release, the remaining tasks have not yet been prioritized. We'll keep them open but in the interest of keeping our task list clean we'll close this umbrella Issue.

bignimbus avatar Sep 29 '23 14:09 bignimbus