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

Cannot Use Amplify-Generated Android Model Files for GraphQL API Requests #2735

Open
1 task done
leomuko opened this issue Mar 13, 2024 · 1 comment
Open
1 task done
Labels
GraphQL API Related to the API (GraphQL) category/plugins question General question

Comments

@leomuko
Copy link

leomuko commented Mar 13, 2024

Before opening, please confirm:

Language and Async Model

Java, Kotlin

Amplify Categories

GraphQL API

Gradle script dependencies

implementation 'com.amplifyframework:core:2.14.6'
implementation 'com.amplifyframework:aws-api:2.14.5'

Environment information

# Put output below this line


Please include any relevant guides or documentation you're referencing

https://docs.amplify.aws/android/build-a-backend/graphqlapi/advanced-workflows

Describe the bug

During the development of our Android application, I utilized Amplify's codegen tool to generate model files intended for interfacing with our GraphQL API. These generated files encompass classes that either extend the Model class or are simple Java model classes.

According to the provided documentation, these generated model files should seamlessly facilitate requests to our GraphQL API. However, upon attempting to utilize these files for making requests, we encountered unexpected results. Instead of successful interactions with the API, parsing issues within Amplify arose, leading to the generation of errors.

Notably, the response is returned as a string.

It's worth noting that the files extending the Model class seem to work fine, whereas the "simple Java files" do not return expected results.

Our objective is to leverage these generated model files for Amplify requests, streamlining our process and ensuring smoother migrations of future changes. Currently, we are resorting to using custom files for parsing responses, which adds complexity to our workflow.

I am seeking clarification on the root cause of these parsing failures. I have diligently followed the steps outlined in the AWS documentation. Any insights or assistance in resolving this issue would be greatly appreciated.

Reproduction steps (if applicable)

No response

Code Snippet

fun testGetBatchTeam() : GraphQLRequest<BatchGetTeamOutput>{
        val document = "query BatchGetTeam(" +
                "    \$orgID: ID!\n" +
                "    \$roleSKs: [ID]\n" +
                "    \$deptSKs: [ID]\n" +
                "    \$locationSKs: [ID]\n" +
                "    \$memberSKs: [ID]) {\n" +
                "  BatchGetTeam(" +
                "      orgID: \$orgID\n" +
                "      roleSKs: \$roleSKs\n" +
                "      deptSKs: \$deptSKs\n" +
                "      locationSKs: \$locationSKs\n" +
                "      memberSKs: \$memberSKs) {\n" +
                "    roles {\n" +
                "      id\n" +
                "      orgID\n" +
                "      sortKey\n" +
                "      itemType\n" +
                "      createdAt\n" +
                "      createdBy\n" +
                "      updatedAt\n" +
                "      updatedBy\n" +
                "      roleName\n" +
                "      canManageOrgAccount\n" +
                "      canManageOrgInfo\n" +
                "      canManageSubscriptions\n" +
                "      canManageTeamStructure\n" +
                "      canManageMembers\n" +
                "      canRemoveMembers\n" +
                "      canManageChannels\n" +
                "      canManagePosts\n" +
                "      canCreateTeamStructure\n" +
                "      canCreateMembers\n" +
                "      canCreateChannels\n" +
                "      canCreatePublicChannels\n" +
                "      canCreateRoleBasedChannels\n" +
                "      canCreatePosts\n" +
                "      deletedAt\n" +
                "      deletedBy\n" +
                "    }\n" +
                "    depts {\n" +
                "      id\n" +
                "      orgID\n" +
                "      sortKey\n" +
                "      itemType\n" +
                "      createdAt\n" +
                "      createdBy\n" +
                "      updatedAt\n" +
                "      updatedBy\n" +
                "      deptName\n" +
                "      deletedAt\n" +
                "      deletedBy\n" +
                "    }\n" +
                "    locations {\n" +
                "      id\n" +
                "      orgID\n" +
                "      sortKey\n" +
                "      itemType\n" +
                "      createdAt\n" +
                "      createdBy\n" +
                "      updatedAt\n" +
                "      updatedBy\n" +
                "      locationName\n" +
                "      deletedAt\n" +
                "      deletedBy\n" +
                "    }\n" +
                "    members {\n" +
                "      id\n" +
                "      orgID\n" +
                "      sortKey\n" +
                "      itemType\n" +
                "      createdAt\n" +
                "      createdBy\n" +
                "      updatedAt\n" +
                "      updatedBy\n" +
                "      userID\n" +
                "      chatUserID\n" +
                "      chatSystemChannel\n" +
                "      fullName\n" +
                "      profilePhoto {\n" +
                "        cfImageHash\n" +
                "        cfImageID\n" +
                "      }\n" +
                "      employeeID\n" +
                "      assignedDepts\n" +
                "      assignedLocations\n" +
                "      assignedRoles\n" +
                "      deactivatedAt\n" +
                "      deactivatedBy\n" +
                "      deletedAt\n" +
                "      deletedBy\n" +
                "      phoneNumber\n" +
                "    }\n" +
                "    unprocessedMembers {\n" +
                "      orgID\n" +
                "      sortKey\n" +
                "    }\n" +
                "    unprocessedLocations {\n" +
                "      orgID\n" +
                "      sortKey\n" +
                "    }\n" +
                "    unprocessedDepts {\n" +
                "      orgID\n" +
                "      sortKey\n" +
                "    }\n" +
                "    unprocessedRoles {\n" +
                "      orgID\n" +
                "      sortKey\n" +
                "    }\n" +
                "  }\n" +
                "}"

        return SimpleGraphQLRequest(
            document,
            mapOf(
                "orgID" to "04a731e8-0fed-401d-80d5-c5c7244b7fc8",
                "roleSKs" to listOf("OWNER"),
                "memberSKs" to listOf("TEAM#MEMBER#2024-02-26T12:10:33.648Z")
            ),
            BatchGetTeamOutput::class.java,
            GsonVariablesSerializer()
        )
    }
package co.heyinnovation.desklessworkers.data.models.amplify.generated.model;


import androidx.core.util.ObjectsCompat;

import java.util.Objects;
import java.util.List;

/** This is an auto generated class representing the BatchGetTeamOutput type in your schema. */
public final class BatchGetTeamOutput {
  private final List<Role> roles;
  private final List<Department> depts;
  private final List<Location> locations;
  private final List<Member> members;
  private final List<UnprocessedKeysForOrganisation> unprocessedMembers;
  private final List<UnprocessedKeysForOrganisation> unprocessedLocations;
  private final List<UnprocessedKeysForOrganisation> unprocessedDepts;
  private final List<UnprocessedKeysForOrganisation> unprocessedRoles;
  public List<Role> getRoles() {
      return roles;
  }
  
  public List<Department> getDepts() {
      return depts;
  }
  
  public List<Location> getLocations() {
      return locations;
  }
  
  public List<Member> getMembers() {
      return members;
  }
  
  public List<UnprocessedKeysForOrganisation> getUnprocessedMembers() {
      return unprocessedMembers;
  }
  
  public List<UnprocessedKeysForOrganisation> getUnprocessedLocations() {
      return unprocessedLocations;
  }
  
  public List<UnprocessedKeysForOrganisation> getUnprocessedDepts() {
      return unprocessedDepts;
  }
  
  public List<UnprocessedKeysForOrganisation> getUnprocessedRoles() {
      return unprocessedRoles;
  }
  
  private BatchGetTeamOutput(List<Role> roles, List<Department> depts, List<Location> locations, List<Member> members, List<UnprocessedKeysForOrganisation> unprocessedMembers, List<UnprocessedKeysForOrganisation> unprocessedLocations, List<UnprocessedKeysForOrganisation> unprocessedDepts, List<UnprocessedKeysForOrganisation> unprocessedRoles) {
    this.roles = roles;
    this.depts = depts;
    this.locations = locations;
    this.members = members;
    this.unprocessedMembers = unprocessedMembers;
    this.unprocessedLocations = unprocessedLocations;
    this.unprocessedDepts = unprocessedDepts;
    this.unprocessedRoles = unprocessedRoles;
  }
  
  @Override
   public boolean equals(Object obj) {
      if (this == obj) {
        return true;
      } else if(obj == null || getClass() != obj.getClass()) {
        return false;
      } else {
      BatchGetTeamOutput batchGetTeamOutput = (BatchGetTeamOutput) obj;
      return ObjectsCompat.equals(getRoles(), batchGetTeamOutput.getRoles()) &&
              ObjectsCompat.equals(getDepts(), batchGetTeamOutput.getDepts()) &&
              ObjectsCompat.equals(getLocations(), batchGetTeamOutput.getLocations()) &&
              ObjectsCompat.equals(getMembers(), batchGetTeamOutput.getMembers()) &&
              ObjectsCompat.equals(getUnprocessedMembers(), batchGetTeamOutput.getUnprocessedMembers()) &&
              ObjectsCompat.equals(getUnprocessedLocations(), batchGetTeamOutput.getUnprocessedLocations()) &&
              ObjectsCompat.equals(getUnprocessedDepts(), batchGetTeamOutput.getUnprocessedDepts()) &&
              ObjectsCompat.equals(getUnprocessedRoles(), batchGetTeamOutput.getUnprocessedRoles());
      }
  }
  
  @Override
   public int hashCode() {
    return new StringBuilder()
      .append(getRoles())
      .append(getDepts())
      .append(getLocations())
      .append(getMembers())
      .append(getUnprocessedMembers())
      .append(getUnprocessedLocations())
      .append(getUnprocessedDepts())
      .append(getUnprocessedRoles())
      .toString()
      .hashCode();
  }
  
  public static BuildStep builder() {
      return new Builder();
  }
  
  public CopyOfBuilder copyOfBuilder() {
    return new CopyOfBuilder(roles,
      depts,
      locations,
      members,
      unprocessedMembers,
      unprocessedLocations,
      unprocessedDepts,
      unprocessedRoles);
  }
  public interface BuildStep {
    BatchGetTeamOutput build();
    BuildStep roles(List<Role> roles);
    BuildStep depts(List<Department> depts);
    BuildStep locations(List<Location> locations);
    BuildStep members(List<Member> members);
    BuildStep unprocessedMembers(List<UnprocessedKeysForOrganisation> unprocessedMembers);
    BuildStep unprocessedLocations(List<UnprocessedKeysForOrganisation> unprocessedLocations);
    BuildStep unprocessedDepts(List<UnprocessedKeysForOrganisation> unprocessedDepts);
    BuildStep unprocessedRoles(List<UnprocessedKeysForOrganisation> unprocessedRoles);
  }
  

  public static class Builder implements BuildStep {
    private List<Role> roles;
    private List<Department> depts;
    private List<Location> locations;
    private List<Member> members;
    private List<UnprocessedKeysForOrganisation> unprocessedMembers;
    private List<UnprocessedKeysForOrganisation> unprocessedLocations;
    private List<UnprocessedKeysForOrganisation> unprocessedDepts;
    private List<UnprocessedKeysForOrganisation> unprocessedRoles;
    public Builder() {
      
    }
    
    private Builder(List<Role> roles, List<Department> depts, List<Location> locations, List<Member> members, List<UnprocessedKeysForOrganisation> unprocessedMembers, List<UnprocessedKeysForOrganisation> unprocessedLocations, List<UnprocessedKeysForOrganisation> unprocessedDepts, List<UnprocessedKeysForOrganisation> unprocessedRoles) {
      this.roles = roles;
      this.depts = depts;
      this.locations = locations;
      this.members = members;
      this.unprocessedMembers = unprocessedMembers;
      this.unprocessedLocations = unprocessedLocations;
      this.unprocessedDepts = unprocessedDepts;
      this.unprocessedRoles = unprocessedRoles;
    }
    
    @Override
     public BatchGetTeamOutput build() {
        
        return new BatchGetTeamOutput(
          roles,
          depts,
          locations,
          members,
          unprocessedMembers,
          unprocessedLocations,
          unprocessedDepts,
          unprocessedRoles);
    }
    
    @Override
     public BuildStep roles(List<Role> roles) {
        this.roles = roles;
        return this;
    }
    
    @Override
     public BuildStep depts(List<Department> depts) {
        this.depts = depts;
        return this;
    }
    
    @Override
     public BuildStep locations(List<Location> locations) {
        this.locations = locations;
        return this;
    }
    
    @Override
     public BuildStep members(List<Member> members) {
        this.members = members;
        return this;
    }
    
    @Override
     public BuildStep unprocessedMembers(List<UnprocessedKeysForOrganisation> unprocessedMembers) {
        this.unprocessedMembers = unprocessedMembers;
        return this;
    }
    
    @Override
     public BuildStep unprocessedLocations(List<UnprocessedKeysForOrganisation> unprocessedLocations) {
        this.unprocessedLocations = unprocessedLocations;
        return this;
    }
    
    @Override
     public BuildStep unprocessedDepts(List<UnprocessedKeysForOrganisation> unprocessedDepts) {
        this.unprocessedDepts = unprocessedDepts;
        return this;
    }
    
    @Override
     public BuildStep unprocessedRoles(List<UnprocessedKeysForOrganisation> unprocessedRoles) {
        this.unprocessedRoles = unprocessedRoles;
        return this;
    }
  }
  

  public final class CopyOfBuilder extends Builder {
    private CopyOfBuilder(List<Role> roles, List<Department> depts, List<Location> locations, List<Member> members, List<UnprocessedKeysForOrganisation> unprocessedMembers, List<UnprocessedKeysForOrganisation> unprocessedLocations, List<UnprocessedKeysForOrganisation> unprocessedDepts, List<UnprocessedKeysForOrganisation> unprocessedRoles) {
      super(roles, depts, locations, members, unprocessedMembers, unprocessedLocations, unprocessedDepts, unprocessedRoles);
      
    }
    
    @Override
     public CopyOfBuilder roles(List<Role> roles) {
      return (CopyOfBuilder) super.roles(roles);
    }
    
    @Override
     public CopyOfBuilder depts(List<Department> depts) {
      return (CopyOfBuilder) super.depts(depts);
    }
    
    @Override
     public CopyOfBuilder locations(List<Location> locations) {
      return (CopyOfBuilder) super.locations(locations);
    }
    
    @Override
     public CopyOfBuilder members(List<Member> members) {
      return (CopyOfBuilder) super.members(members);
    }
    
    @Override
     public CopyOfBuilder unprocessedMembers(List<UnprocessedKeysForOrganisation> unprocessedMembers) {
      return (CopyOfBuilder) super.unprocessedMembers(unprocessedMembers);
    }
    
    @Override
     public CopyOfBuilder unprocessedLocations(List<UnprocessedKeysForOrganisation> unprocessedLocations) {
      return (CopyOfBuilder) super.unprocessedLocations(unprocessedLocations);
    }
    
    @Override
     public CopyOfBuilder unprocessedDepts(List<UnprocessedKeysForOrganisation> unprocessedDepts) {
      return (CopyOfBuilder) super.unprocessedDepts(unprocessedDepts);
    }
    
    @Override
     public CopyOfBuilder unprocessedRoles(List<UnprocessedKeysForOrganisation> unprocessedRoles) {
      return (CopyOfBuilder) super.unprocessedRoles(unprocessedRoles);
    }
  }
  
}

Log output

//Response is -----
GraphQLResponse{data='co.heyinnovation.desklessworkers.data.models.amplify.generated.model.BatchGetTeamOutput@2b6d2a38', errors='[]'}

amplifyconfiguration.json

No response

GraphQL Schema

No response

Additional information and screenshots

No response

@github-actions github-actions bot added the pending-triage Issue is pending triage label Mar 13, 2024
@leomuko leomuko changed the title Cannot Amplify-Generated Android Model Files for GraphQL API Requests Cannot Use Amplify-Generated Android Model Files for GraphQL API Requests Mar 13, 2024
@yuhengshs yuhengshs added datastore DataStore category/plugins investigating This issue is being investigated api GraphQL API Related to the API (GraphQL) category/plugins question General question pending-response Issue is pending response from the issue requestor and removed pending-triage Issue is pending triage datastore DataStore category/plugins investigating This issue is being investigated question General question api labels Mar 13, 2024
@yuhengshs
Copy link
Contributor

yuhengshs commented Mar 15, 2024

Hi @leomuko ,

Someone on our team is taking a look at the issue and will get back to you as soon as we have something.

Thanks for your patience!

@github-actions github-actions bot removed the pending-response Issue is pending response from the issue requestor label Mar 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GraphQL API Related to the API (GraphQL) category/plugins question General question
Projects
None yet
Development

No branches or pull requests

2 participants