aws-amplify / aws-amplify/amplify-android

[DataStore] @hasMany connection to another model returns null inside query and crashes app

Open
#1,676 11 comments 0 reactions 0 assignees View on GitHub
datastore feature-request
Dominant language
Java
Stars
287
Forks
132
Avg merge
2d 2h
Merged PRs (30d)
45

Description

### Before opening, please confirm:

- [X] I have [searched for duplicate or closed issues](https://github.com/aws-amplify/amplify-android/issues?q=is%3Aissue+) and [discussions](https://github.com/aws-amplify/amplify-android/discussions).

### Language and Async Model

Kotlin - Coroutines

### Amplify Categories

DataStore

### Gradle script dependencies

```groovy
// Put output below this line

// Amplify core dependency
implementation 'com.amplifyframework:core:1.32.1'
implementation 'com.amplifyframework:core-kotlin:0.16.0'
implementation 'com.amplifyframework:aws-api:1.32.1'
implementation 'com.amplifyframework:aws-datastore:1.32.1'
```

### Environment information

```
# Put output below this line

------------------------------------------------------------
Gradle 7.2
------------------------------------------------------------

Build time: 2021-08-17 09:59:03 UTC
Revision: a773786b58bb28710e3dc96c4d1a7063628952ad

Kotlin: 1.5.21
Groovy: 3.0.8
Ant: Apache Ant(TM) version 1.10.9 compiled on September 27 2020
JVM: 17.0.1 (Oracle Corporation 17.0.1+12-39)
OS: Mac OS X 12.1 aarch64

```

### Please include any relevant guides or documentation you're referencing

https://docs.amplify.aws/lib/datastore/relational/q/platform/android/

### Describe the bug

I am trying to access nested model (Blog & Post in schema) inside DataStore queries similar to how it is possible to access Nested CustomType (which works). In the code, when trying to access the (Mutable)List, I get a null pointer error and my app crashes. I have been facing this issue since amplifyframework version 1.31.3 and now I am on 1.32.x and still facing it.

Any ideas or suggestions?

This seems to be working on other platforms.
On Flutter, https://github.com/aws-amplify/amplify-flutter/issues/260#issuecomment-909679333 mentions that [CustomType] is not supported but that works on my end. Only [AnotherModel] i.e. a @hasMany relationship between tables is not working.

### Reproduction steps (if applicable)

1. Set up env with provided GraphQL Schema
2. Notice that list of CustomType is working fine and is accessible.
3. But, list of AnotherModel is not accessible/returns null and crashes app.
4. This seems to work on iOS, Flutter and JS, but only fails on Native Android (Kotlin)

### Code Snippet

```kotlin
// Put your code below this line.
GlobalScope.launch {
Amplify.DataStore.query(Blog::class, Where.id("1"))
.catch { Log.e("DataStore", "Error", it)}
.collect {
Log.d("DataStore", "${it.id}, ${it.name}, ${it.customs}")
Log.d("DataStore", it.customs[1].children[0].nestedName + ", customs size: ${it.customs.size}")
// the next line returns null and crashes app
Log.d("DataStore", "posts test id: ${it.post[0].id}")
}
}
```

### Log output

```
// Put your logs below this line
E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: com.example.datastorecrud, PID: 22111
java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.List.get(int)' on a null object reference
at com.example.datastorecrud.MainActivity$onCreate$1$invokeSuspend$$inlined$collect$1.emit(Collect.kt:136)
at kotlinx.coroutines.flow.FlowKt__ErrorsKt$catchImpl$$inlined$collect$1.emit(Collect.kt:134)
at kotlinx.coroutines.flow.FlowKt__ChannelsKt.emitAllImpl$FlowKt__ChannelsKt(Channels.kt:61)
at kotlinx.coroutines.flow.FlowKt__ChannelsKt$emitAllImpl$1.invokeSuspend(Unknown Source:11)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

```

### amplifyconfiguration.json

_No response_

### GraphQL Schema

```graphql
// Put your schema below this line

type Blog @model {
id: ID!
name: String!
customs: [MyCustomModel]
notes: [String]
post: [Post] @hasMany(indexName: "postByBlog", fields: ["id"])
}

type MyCustomModel {
id: ID!
name: String!
desc: String
children: [MyNestedModel]
}

type MyNestedModel {
id: ID!
nestedName: String!
notes: [String]
}

type Post @model {
id:ID!
name:String!
blog_id: ID! @index(name: "postByBlog")
blog: Blog @belongsTo(fields: ["blog_id"])
}

```

### Additional information and screenshots

_No response_

Contributor guide

Open the contributing guide

Research direction

Begin at the Amplify.DataStore.query(Blog::class, Where.id("1")) call and reproduce it with the supplied Blog/Post @hasMany schema and Kotlin snippet. Compare the working custom-type access with the null Post list; done means the relationship can be queried without the reported NullPointerException.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, aws, kotlin
Domain
database, mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.