aws-amplify / amplify-android

The fastest and easiest way to use AWS from your Android app.
https://docs.amplify.aws/lib/q/platform/android/
Apache License 2.0
244 stars 114 forks source link

"Error Occurs When Filtering API Queries Using Owner and Input Type with Generated GraphQL Schema (schema.json, mutations.graphql, queries.graphql, fragments.graphql, subscriptions.graphql) #2884

Open Jaff5090 opened 1 month ago

Jaff5090 commented 1 month ago

Before opening, please confirm:

Language and Async Model

Kotlin

Amplify Categories

GraphQL API

Gradle script dependencies

```groovy // Put output below this line implementation("com.amazonaws:aws-android-sdk-appsync:3.4.1") implementation ("com.amplifyframework:core:2.19.1") implementation ("com.amplifyframework:aws-api:2.19.1") implementation("com.amplifyframework:aws-auth-cognito:2.19.1") implementation ("com.amplifyframework:aws-storage-s3:2.19.1") ```

Environment information

``` ------------------------------------------------------------ Gradle 8.6 ------------------------------------------------------------ Build time: 2024-02-02 16:47:16 UTC Revision: d55c486870a0dc6f6278f53d21381396d0741c6e Kotlin: 1.9.20 Groovy: 3.0.17 Ant: Apache Ant(TM) version 1.10.13 compiled on January 4 2023 JVM: 17.0.10 (Oracle Corporation 17.0.10+11-LTS-240) OS: Windows 10 10.0 amd64 ```

Please include any relevant guides or documentation you're referencing

No response

Describe the bug

We are working on a project where the same API is used for both a web app and a mobile app. To integrate this API into the mobile app, I used AWS Amplify with the following commands to generate the necessary configurations:

amplify codegen add --apiId XXXXXX --region <Your-Region>

This command generated the graphqlconfig.yml file along with fragments.graphql, mutations.graphql, subscriptions.graphql, and queries.graphql files. These files were then used to generate the corresponding Java classes that allow interaction with the API.

I then used these generated classes to make API requests, specifically to retrieve a list of sessions. When I make a request to retrieve the full list of sessions, it works correctly, and I receive all available sessions.

Problem:

The issue arises when I try to filter the list of sessions using an owner field and an input of type Session. Here's an example of the query I’m using to filter

Reproduction steps (if applicable)

No response

Code Snippet

``Kotlin suspend fun getSessions(userId: String): List? { val sessionFilterInput = ModelSessionFilterInput.builder() .owner(ModelStringInput.builder().eq(userId).build()) .archived(ModelBooleanInput.builder().eq(false).build()) .build()

    val query = ListSessionsQuery.builder()
        .limit(Int.MAX_VALUE)
        .filter(sessionFilterInput)
        .build()

    val variablesMap = query.variables().valueMap()

    val request = SimpleGraphQLRequest<ListSessionsQuery.Data>(
        query.queryDocument(),
        variablesMap,
        ListSessionsQuery.Data::class.java,
        GsonVariablesSerializer()
    )

    Log.d("SessionRepository", "Query Document: ${query.queryDocument()}")
    Log.d("SessionRepository", "Variables: $variablesMap")

    return withContext(Dispatchers.IO) {
        suspendCancellableCoroutine { continuation ->
            Amplify.API.query(
                request,
                { response ->
                    if (response.data != null) {
                        continuation.resume(response.data.listSessions()?.items())
                    } else {
                        continuation.resumeWithException(Exception(response.errors.toString()))
                    }
                },
                { error ->
                    Log.e("SessionRepository", "Query session error", error)
                    continuation.resumeWithException(error)
                }
            )
        }
    }
}

### Log output

<details>

``` ERROR

 **Process: com.example.myvisitlive, PID: 3841
  java.lang.Exception: [GraphQLResponse.Error{message='The variables input contains a field that is not defined for input object type 'ModelSessionFilterInput' ', locations='null', path='null', extensions='null'
at com.example.myvisitlive.repository.SessionRepository$getSessions$2$1$1.accept(SessionRepository.kt:101)
at com.example.myvisitlive.repository.SessionRepository$getSessions$2$1$1.accept(SessionRepository.kt:95)at com.amplifyframework.api.aws.AppSyncGraphQLOperation$OkHttpCallback.onResponse(AppSyncGraphQLOperation.java:153)at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:529)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
   at java.lang.Thread.run(Thread.java:1012)
   Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@e8cc236, 
   Dispatchers.Main.immediate]**

amplifyconfiguration.json

{
    "UserAgent": "aws-amplify-cli/2.0",
    "Version": "1.0",
    "api": {
        "plugins": {
            "awsAPIPlugin": {
                "front-stgxix": {
                    "endpointType": "GraphQL",
                    "endpoint": "https://xxxxxxxxxxxxxxx.appsync-api.eu-central-1.amazonaws.com/graphql",
                    "region": "eu-central-1",
                    "authorizationType": "AMAZON_COGNITO_USER_POOLS",
                    "apiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxx"
                }
            }
        }
    },
    "auth": {
        "plugins": {
            "awsCognitoAuthPlugin": {
                "UserAgent": "aws-amplify-cli/0.1.0",
                "Version": "0.1.0",
                "IdentityManager": {
                    "Default": {}
                },
                "AppSync": {
                    "Default": {
                        "ApiUrl": "https://xxxxxxxxxxxxxxxxxxxxx.appsync-api.eu-central-1.amazonaws.com/graphql",
                        "Region": "eu-central-1",
                        "AuthMode": "AMAZON_COGNITO_USER_POOLS",
                        "ClientDatabasePrefix": "front-stgxix_AMAZON_COGNITO_USER_POOLS"
                    },
                    "front-stgxix_API_KEY": {
                        "ApiUrl": "https://vyckjxsws5btddyckwjdnfhw7y.appsync-api.eu-central-1.amazonaws.com/graphql",
                        "Region": "eu-central-1",
                        "AuthMode": "API_KEY",
                        "ApiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
                        "ClientDatabasePrefix": "front-stgxix_API_KEY"
                    }
                },
                "CredentialsProvider": {
                    "CognitoIdentity": {
                        "Default": {
                            "PoolId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                            "Region": "eu-central-1"
                        }
                    }
                },
                "CognitoUserPool": {
                    "Default": {
                        "PoolId": "eu-central-1_xxxxxxxxxxxx",
                        "AppClientId": "xxxxxxxxxxxxxxxx",
                        "Region": "eu-central-1",
                        "AppClientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                    }
                },
                "Auth": {
                    "Default": {
                        "authenticationFlowType": "CUSTOM_AUTH",
                        "socialProviders": [],
                        "usernameAttributes": [
                            "EMAIL"
                        ],
                        "signupAttributes": [
                            "EMAIL"
                        ],
                        "passwordProtectionSettings": {
                            "passwordPolicyMinLength": 8,
                            "passwordPolicyCharacters": []
                        },
                        "mfaConfiguration": "OFF",
                        "mfaTypes": [],
                        "verificationMechanisms": [
                            "EMAIL"
                        ]
                    }
                },
                "S3TransferUtility": {
                    "Default": {
                        "Bucket": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-stgxix",
                        "Region": "eu-central-1"
                    }
                }
            }
        }
    },
    "storage": {
        "plugins": {
            "awsS3StoragePlugin": {
                "bucket": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-stgxix",
                "region": "eu-central-1",
                "defaultAccessLevel": "guest"
            }
        }
    }
}

GraphQL Schema

i have only a schema.json file along with four GraphQL schema files: mutations.graphql, queries.graphql, fragments.graphql, and subscriptions.graphql

Additional information and screenshots

image image

mattcreaser commented 1 month ago

Thank you for the detailed bug report. We'll need to try to reproduce this to see what is going on. It would be very helpful if you could share the content of your GraphQL files (feel free to just include the models in your reproduction steps).

tylerjroach commented 1 month ago

Hi @Jaff5090,

It appears that you may be attempting to use .graphql files generated for the AWS Mobile AppSync SDK Android and not the Amplify models.

Amplify API requires Java models generated from the Amplify API schema.graphql file, and generated via amplify codegen models command.

Do you have an Amplify schema.graphql file? If so, can you share what your Java models look like?

I see that you have both: implementation("com.amazonaws:aws-android-sdk-appsync:3.4.1") and implementation ("com.amplifyframework:aws-api:2.19.1"). I would expect that you would be using only one of these libraries and not both.

Jaff5090 commented 1 month ago

@tylerjroach @mattcreaser Hello ,

Thank you for your feedback and the detailed bug report. Currently, I don't have access to the schema.graphql file because our team uses a shared graph schema for the project. The web app pushes changes to the API, and I only perform GET PULL API . As a result, I don't generate Java models from a schema.graphql file.

Thank you for your understanding.

Best regards,

tylerjroach commented 1 month ago

@Jaff5090

These files were then used to generate the corresponding Java classes that allow interaction with the API.

How are you creating the Java files? Are they being created through this library? https://github.com/awslabs/aws-mobile-appsync-sdk-android

If so, you would need to use the AppSync SDK library instead of Amplify API library.

If your team is using Amplify API (and not just AppSync directly), the schema.graphql is necessary to generate the Java model files: https://docs.amplify.aws/gen1/android/build-a-backend/graphqlapi/client-code-generation/#generate-models-for-android-swift-flutter-and-javascript-datastore