Cannot Use Amplify-Generated Android Model Files for GraphQL API Requests
Before opening, please confirm:
- [X] I have searched for duplicate or closed issues and discussions.
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
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!
Sorry for the late response here.
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.
I believe this is expected. Can you point to documentation that you are attempting to follow? Amplify GraphQL API is primarily intended to be used with Amplify models, especially when it comes to serialization.