awslabs / aws-mobile-appsync-sdk-android

Android SDK for AWS AppSync.
https://docs.amplify.aws/sdk/api/graphql/q/platform/android/
Apache License 2.0
105 stars 58 forks source link

AWSAppSyncClient is not generating code from the graphql file in Android #408

Closed Dharan23 closed 1 year ago

Dharan23 commented 1 year ago

I'm trying to use AWSAppSyncClient with Amplify in Android. We have an existing schema in AWS console which the other platforms like IOS and Web are using. So I want to use AWSAppSyncClient to call the api instead of using Amplify. But I am facing issue like it is not generating any API layer for me to consume (like it does for IOS).

My Schema sample:

type Location {
  location_id: String!
  location_name: String!
}
type Role {
  role_id: String!
  role_name: String!
}

What should I do to generate Model and API from this schema file? Please help me with an answer

gpanshu commented 1 year ago

Hi @Dharan23 what steps have you tried on cli ? Have you tried amplify codegen models on your cmd line?

div5yesh commented 1 year ago

Please refer to this codegen documentation: https://docs.amplify.aws/sdk/api/graphql/q/platform/android/#code-generation

Dharan23 commented 1 year ago

I am using the amplify codegen models but it is not generating any models because i am not writing my schema files and pushing it to the console through CLI. I am using an already existing resource. So I will just have the .graphql file shared to me. Because of that I am not doing any amplify init in my project. Does AWSAppSync generate models and API for us to consume if we just have the .graphql file in a specific location in the project without doing any of amplify init? Because this approach is working for IOS but not for Android so I am curious if the Android SDK has such support.

gpanshu commented 1 year ago

Can you share the output of amplify status ?

Dharan23 commented 1 year ago

Yes i tried amplify status.. because i am not doing amplify init (because i will be using existing resource) it shows me below error.

image

Dharan23 commented 1 year ago

to use existing resource i am doing amplify pull.. this is what I'm getting

image

gpanshu commented 1 year ago

That's what I thought. Your environment is not configured. You can even pull a specific project down. Go to your amplify console and pull that project ID to see if that works.

gpanshu commented 1 year ago

Just to clarify a little here are the steps you would need to take to pull https://docs.amplify.aws/cli/start/workflows/#amplify-pull

Dharan23 commented 1 year ago

Sure thank you I will try this solution. I have one more question I followed these steps in README.md and I am trying to include the AWSAppSyncClient dependency to my android project.

When I add the dependency (classpath in build (proj), plugin in build (app) and dependency) I am getting this error below. What should I do to solve this?

Note: I am using Android studio Electric Eel 2022.1.1 Patch 2

FAILURE: Build completed with 2 failures.

1: Task failed with an exception.

2: Task failed with an exception.

gpanshu commented 1 year ago

See if this workaround solves your issue : https://github.com/awslabs/aws-mobile-appsync-sdk-android/issues/377#issuecomment-1090239850

Dharan23 commented 1 year ago

This solution is not working as well.. I'm not even able to sync my project after this.

the error i'm getting..

Caused by: org.gradle.internal.metaobject.AbstractDynamicObject$CustomMessageMissingMethodException: Could not find method node() for arguments [build_aw1jn4ogdai8pbr597637y56$_run_closure1$_closure10@1c9f449] on extension 'android' of type com.android.build.gradle.internal.dsl.BaseAppModuleExtension. at org.gradle.internal.metaobject.AbstractDynamicObject$CustomMissingMethodExecutionFailed.(AbstractDynamicObject.java:190) at org.gradle.internal.metaobject.AbstractDynamicObject.methodMissingException(AbstractDynamicObject.java:184) at org.gradle.internal.metaobject.ConfigureDelegate.invokeMethod(ConfigureDelegate.java:86) at build_aw1jn4ogdai8pbr597637y56$_run_closure1.doCall(C:\Users\mbaranidharan\Desktop...\app\build.gradle:46) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at org.gradle.util.internal.ClosureBackedAction.execute(ClosureBackedAction.java:73) at org.gradle.util.internal.ConfigureUtil.configureTarget(ConfigureUtil.java:155) at org.gradle.util.internal.ConfigureUtil.configure(ConfigureUtil.java:106) at org.gradle.util.internal.ConfigureUtil$WrappedConfigureAction.execute(ConfigureUtil.java:167) at org.gradle.internal.extensibility.ExtensionsStorage$ExtensionHolder.configure(ExtensionsStorage.java:173) at org.gradle.internal.extensibility.ExtensionsStorage.configureExtension(ExtensionsStorage.java:64) at org.gradle.internal.extensibility.DefaultConvention.configureExtension(DefaultConvention.java:364) at org.gradle.internal.extensibility.DefaultConvention.access$500(DefaultConvention.java:45) at org.gradle.internal.extensibility.DefaultConvention$ExtensionsDynamicObject.tryInvokeMethod(DefaultConvention.java:301) at org.gradle.internal.metaobject.CompositeDynamicObject.tryInvokeMethod(CompositeDynamicObject.java:98) at org.gradle.internal.extensibility.MixInClosurePropertiesAsMethodsDynamicObject.tryInvokeMethod(MixInClosurePropertiesAsMethodsDynamicObject.java:34) at org.gradle.groovy.scripts.BasicScript$ScriptDynamicObject.tryInvokeMethod(BasicScript.java:135) at org.gradle.internal.metaobject.AbstractDynamicObject.invokeMethod(AbstractDynamicObject.java:163) at org.gradle.groovy.scripts.BasicScript.invokeMethod(BasicScript.java:84) at build_aw1jn4ogdai8pbr597637y56.run(C:\Users\mbaranidharan\Desktop...\app\build.gradle:9) at org.gradle.groovy.scripts.internal.DefaultScriptRunnerFactory$ScriptRunnerImpl.run(DefaultScriptRunnerFactory.java:91) ... 177 more

Is there a Kotlin equivalent of this library? We are not declaring classpath in build.gradle anymore as classpath instead we are using

plugins {
    id 'com.android.application' version '7.4.1' apply false
}

but the SDK documentation says to use classpath. Is there a way to use the library without any issue in new version of Android studio?

Dharan23 commented 1 year ago

This is what we are trying to achieve by using existing resource in our project instead of using Amplify to create a profile. We need AWSAppSycnCLient to talk to our endpoints. Please help us. Your responses are much appreciated.

gpanshu commented 1 year ago

Hi @Dharan23 please paste your entire dependencies block from gradle so that I can understand which versions of our libraries you are using.

Dharan23 commented 1 year ago

@gpanshu These are my dependencies in the entire application.

build.gradle (app)

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-kapt'
    id 'com.google.dagger.hilt.android'
    id 'kotlin-parcelize'
    id 'com.amazonaws.appsync'
}

....

dependencies {

    implementation 'androidx.core:core-ktx:1.9.0'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.8.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation "androidx.recyclerview:recyclerview:1.2.1"

    // Navigation dependencies
    implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
    implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'

    // Dagger hilt dependencies
    implementation 'com.google.dagger:hilt-android:2.44.2'
    implementation 'androidx.core:core-ktx:1.9.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
    kapt "com.google.dagger:hilt-compiler:2.44"
    implementation 'com.google.dagger:hilt-android-compiler:2.44.2'
    implementation 'com.google.dagger:hilt-android-testing:2.44.2'

    // Lifecycle dependencies
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

    // GSON Library
    implementation 'com.google.code.gson:gson:2.10.1'

    // Retrofit for NetworkCall
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2'
    implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'

    // Glide for image icon
    implementation 'com.github.bumptech.glide:glide:4.14.2'
    implementation 'androidx.activity:activity-ktx:1.6.1'

    // AWS dependencies
    // Amplify core dependency
    implementation 'com.amplifyframework:core:2.2.2'
    implementation 'com.amplifyframework:core-kotlin:2.2.2'
    implementation 'com.amplifyframework:aws-api:2.2.2'
    implementation 'com.amplifyframework:aws-auth-cognito:2.2.2'
    implementation 'com.amazonaws:aws-android-sdk-appsync:3.3.1'

    // Support for Java 8 features
    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
    implementation 'com.squareup.okhttp3:okhttp:4.10.0'

    // Test Cases Dependencies
    testImplementation 'junit:junit:4.13.2'
    testImplementation 'org.mockito:mockito-core:5.1.1'
    testImplementation 'com.google.truth:truth:1.1.3'
    implementation 'androidx.arch.core:core-testing:2.2.0'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'org.mockito:mockito-android:5.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

build.gradle (project)

buildscript {
    repositories {
        maven {
            url "https://plugins.gradle.org/m2/"
        }
        google()
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.3'
        classpath 'com.amazonaws:aws-android-sdk-appsync-gradle-plugin:3.1.3'
    }
}

plugins {
    id 'com.android.application' version '7.4.1' apply false
    id 'com.android.library' version '7.4.1' apply false
    id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
    id 'com.google.dagger.hilt.android' version '2.44' apply false
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

And this is the error I'm getting when I build my project after adding these dependencies

''' FAILURE: Build completed with 2 failures.

1: Task failed with an exception.

2: Task failed with an exception.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See https://docs.gradle.org/7.5/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 19s 29 actionable tasks: 29 executed

'''

gpanshu commented 1 year ago

Are you using a feature that is not available in Amplify from appsync?

Dharan23 commented 1 year ago

I'm using amplify only for cognito (Auth) services and to maintain session in my application. All the other things are maintained in GraphQL we are trying to use AWSAppsyncClient as it helps to talk to GraphQL like an API layer. I cannot use Amplify to directly connect to the backend because we have other platforms (IOS & Web) using the same service and schema is maintained by a different team directly on AWS console. We will just receive a schema from them when new changes happen.

I found a solution to talk to GraphQL service using Retrofit (Android network lib) and I am able to call the service but I need to write my own models and API from schema through this approach. But AWSAppsyncClient will help me to generate these codes for me which makes it much easier.

My additional question to you is does AWSAppSync add any additional security to calling the GraphQL service? Or it is just a code generator which helps developers skip writing API and just focus on business logic.

gpanshu commented 1 year ago

I think you can use Amplify all of that. Amplify V2 should work similarly between iOS and Android and the schema shouldnt be different between the platforms.

Please try using Amplify V2 for your needs as this cross application could be what is causing the issue. Try using Amplify and your original problem of authentication on CLI can be resolved by using the steps I mentioned.

Dharan23 commented 1 year ago

@gpanshu the situation is different in our case. Our backend team has hosted the data using AWSApp sync. Using amplify pull also we can not see any profile because there is nothing created using amplify. So the only way we have is using AWSAppSyncClient, we need to generate our code. We already followed all the steps mentioned here in the link - https://docs.amplify.aws/sdk/api/graphql/q/platform/android/#import-sdk-and-config , but unfortunately we are getting this error - Execution failed for task ':app:nodeSetup' , mentioned already in one the issue open thread and posted our issue on a descriptive way in stackoverflow, you can check this also. @gpanshu  that's the issue where we stuck, not able to go further, without solving the error if we just use the command amplify codegen --apiId **** then graphlql files are only being created nothing relate to java or kotlin being created. That's why posted question here and doing research for so many articles, we come to conclusion that we need to use gradle plugin com.amazonaws.appsync , it will generate the classes for us, you can see this solution provided by a developer.  The conclusion is now we need to solve this error , so that above mentioned gradle plugin will generate the classes for us as mentioned here.

tjleing commented 1 year ago

Hey @Dharan23, above where you linked the docs on reusing existing AppSync resources, that requires an Amplify project to be set up in your local directory. To follow those steps, start with amplify init and amplify push, then add that configuration block to the amplifyconfiguration.json file, so that it is linked to your existing AppSync API. From there, you should be able to use amplify codegen models to connect everything together. It sounds to me like this is exactly the use case you're trying to implement because you're sharing this resource across platforms/apps.

I hope that helps resolve your issue in the short term. We will continue to look into the issue you've reported for now, though.

muditsengar commented 6 months ago

Sure thank you I will try this solution. I have one more question I followed these steps in README.md and I am trying to include the AWSAppSyncClient dependency to my android project.

When I add the dependency (classpath in build (proj), plugin in build (app) and dependency) I am getting this error below. What should I do to solve this?

Note: I am using Android studio Electric Eel 2022.1.1 Patch 2

FAILURE: Build completed with 2 failures.

1: Task failed with an exception.

  • What went wrong: Execution failed for task ':app:nodeSetup'.

Build was configured to prefer settings repositories over project repositories but repository 'ivy' was added by unknown code

  • Try:

Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

2: Task failed with an exception.

  • What went wrong: Execution failed for task ':app:checkDebugDuplicateClasses'.

A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable Duplicate class javax.annotation.Generated found in modules javax.annotation-api-1.3.2 (javax.annotation:javax.annotation-api:1.3.2) and jsr250-api-1.0 (javax.annotation:jsr250-api:1.0) Duplicate class javax.annotation.PostConstruct found in modules javax.annotation-api-1.3.2 (javax.annotation:javax.annotation-api:1.3.2) and jsr250-api-1.0 (javax.annotation:jsr250-api:1.0) Duplicate class javax.annotation.PreDestroy found in modules javax.annotation-api-1.3.2 (javax.annotation:javax.annotation-api:1.3.2) and jsr250-api-1.0 (javax.annotation:jsr250-api:1.0) Duplicate class javax.annotation.Resource found in modules javax.annotation-api-1.3.2 (javax.annotation:javax.annotation-api:1.3.2) and jsr250-api-1.0 (javax.annotation:jsr250-api:1.0) Duplicate class javax.annotation.Resource$AuthenticationType found in modules javax.annotation-api-1.3.2 (javax.annotation:javax.annotation-api:1.3.2) and jsr250-api-1.0 (javax.annotation:jsr250-api:1.0) Duplicate class javax.annotation.Resources found in modules javax.annotation-api-1.3.2 (javax.annotation:javax.annotation-api:1.3.2) and jsr250-api-1.0 (javax.annotation:jsr250-api:1.0) Duplicate class javax.annotation.security.DeclareRoles found in modules javax.annotation-api-1.3.2 (javax.annotation:javax.annotation-api:1.3.2) and jsr250-api-1.0 (javax.annotation:jsr250-api:1.0) Duplicate class javax.annotation.security.DenyAll found in modules javax.annotation-api-1.3.2 (javax.annotation:javax.annotation-api:1.3.2) and jsr250-api-1.0 (javax.annotation:jsr250-api:1.0) Duplicate class javax.annotation.security.PermitAll found in modules javax.annotation-api-1.3.2 (javax.annotation:javax.annotation-api:1.3.2) and jsr250-api-1.0 (javax.annotation:jsr250-api:1.0) Duplicate class javax.annotation.security.RolesAllowed found in modules javax.annotation-api-1.3.2 (javax.annotation:javax.annotation-api:1.3.2) and jsr250-api-1.0 (javax.annotation:jsr250-api:1.0) Duplicate class javax.annotation.security.RunAs found in modules javax.annotation-api-1.3.2 (javax.annotation:javax.annotation-api:1.3.2) and jsr250-api-1.0 (javax.annotation:jsr250-api:1.0)

 Go to the documentation to learn how to <a href="d.android.com/r/tools/classpath-sync-errors">Fix dependency resolution errors</a>.

@Dharan23 Have you found fix of issue? -Build was configured to prefer settings repositories over project repositories but repository 'ivy' was added by unknown code