Amplify-android: Create and update are not working with DataStore version 1.3.2

Created on 16 Sep 2020  路  16Comments  路  Source: aws-amplify/amplify-android

I'm using DataStore, and after I create or update an item and save it to the DataStore, I just see it pending in the logs. Nothing else happens and I see no changes in DynamoDB. It can't sync to the the remote DynamoDB database behind AppSync.

2020-09-16 11:35:23.512 23685-23812/com.spendlee.dev I/amplify:aws-datastore: Successfully enqueued PendingMutation{mutatedItem=Profile

Here's my code:

 try {
    Amplify.addPlugin(AWSCognitoAuthPlugin())
    Amplify.addPlugin(AWSApiPlugin())
    Amplify.addPlugin(AWSDataStorePlugin())
    Amplify.addPlugin(AWSS3StoragePlugin())
    Amplify.configure(applicationContext)
    Log.i("first Initialization", "Initialized Amplify")
} catch (e: AmplifyException) {
    Log.e("first Initialization", "Could not initialize Amplify", e)
}

```kotlin
private fun createProfile(subId: String, spendIee: String, status: String) {
viewModelScope.launch(Dispatchers.IO) {
Amplify.DataStore.query(
Profile::class.java,
Where.id("dummy-query-to-make-datastore-wake-the-**-up"),
{
val profile = Profile.builder()
.username(subId)
.spendleeId(spendIee)
.id(subId)
.state(status)
.avatarImage(null)
.build()
Amplify.DataStore.save(profile,
{ result ->
resCreateProfile.postValue(ResponseHelper.success(result.item()))
observeProfile()
},
{ error ->
resCreateProfile.postValue(
ResponseHelper.error(
error.cause?.message.toString(),
null
)
)
}
)
},
{
Log.i("MyAmplifyApp", "it.cause?.message?.toString()")
}
)
}
}

fun changeProfile(subId: String, spendIee: String, status: String) {
viewModelScope.launch(Dispatchers.IO) {
Amplify.DataStore.query(
Profile::class.java,
Where.id(subId),
{ matches ->
if (matches.hasNext()) {
val original = matches.next()
val edited = original.copyOfBuilder()
.spendleeId(spendIee)
.state(status)
.build()
Amplify.DataStore.save(edited,
{
Log.i("MyAmplifyApp", "Updated a post.")
},
{
Log.e("MyAmplifyApp", "Update failed.", it)
}
)
}
},
{ error ->
Log.e("MyAmplifyApp", error.cause?.message, error)
}
)
}
}


Here's my schema:
```graphql
enum LogEntryType {
  DEBUG
  INFO
  WARNING
  ERROR
}

type LogEntry
  @model
  @key(name: "byUsername", fields: ["username"], queryField: "logEntriesByUsername")
  @auth(
    rules: [
      { allow: public, provider: apiKey }
      { allow: owner, ownerField: "username" }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID!
  username: ID!
  type: String!
  appVersion: String
  appBuild: String
  file: String
  line: Int
  message: String
  data: String
  _ttl: Float
}

enum AdminRequestState {
  REQUESTED
  PROCESSING
  ERROR
  DONE
}

type AdminRequest
  @model
  @auth(
    rules: [
      { allow: public, provider: apiKey }
      { allow: owner, ownerField: "username" }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID!
  username: ID!
  requestType: String!
  _ttl: Float
}
type Merchant
  @model
  @auth(
    rules: [
      { allow: groups, groups: ["appuser"], operations: [read] }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID!
  merchantId: String!
  other: String!
  description: String!
  address: String!
  phoneNumber: String!
  logo: String
}

type Category
  @model
  @auth(
    rules: [
      { allow: groups, groups: ["appuser"], operations: [read] }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID!
  name: String!
}

type Currency
  @model
  @auth(
    rules: [
      { allow: groups, groups: ["appuser"], operations: [read] }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID!
  symbol: String!
  quotedAt: Int!
  rate: Float!
}

type TaxItem
  @model
  @auth(
    rules: [
      { allow: public, provider: apiKey }
      { allow: owner, ownerField: "username" }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID!
  username: ID!
  name: String!
  amount: Float!
  percent: Float!
  #    receipt: Receipt! @connection
}

enum ReceiptState {
  CREATED
  UPLOADING
  EXPORTING
  POSTPONED
  EXPORTED
  UPLOADED
  SCANNING
  READY
  ERROR
}

type Receipt
  @model
  @key(name: "byUsername", fields: ["username"], queryField: "receiptsByUsername")
  @key(name: "byState", fields: ["state"], queryField: "receiptsByState")
  @auth(
    rules: [
      { allow: public, provider: apiKey }
      { allow: owner, ownerField: "username" }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID!
  username: ID!
  state: String
  isFavorite: Boolean
  viewed: Boolean
  error: String
  dateTime: AWSDateTime
  receiptDate: AWSDateTime
  emailDocument: String
  receiptImage: String
  receiptRawText: String
  receiptRawData: String
  merchant: String
  lineItems: AWSJSON
  amount: Float
  taxTotal: Float
  subTotalAmount: Float
  tipAmount: Float
  total: String
}

enum ReceiptExportState {
  REQUESTED
  READY
  ERROR
}

type ReceiptExport
@model
@key(name: "byReceipt", fields: ["receipt"], queryField: "receiptExportsByReceipt")
@auth(
  rules: [
    { allow: public, provider: apiKey }
    { allow: owner, ownerField: "username" }
    { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
  ]
) {
  id: ID!
  username: ID!
  receipt: ID!
  state: String
  url: String
  error: String
}

enum ProfileState {
  CHANGE
  ACCEPT
  INVALID
  DUPLICATE
  OK
  CONFIRMED
}

type Profile
  @model
  @key(name: "byUsername", fields: ["username"], queryField: "profilesByUsername")
  @key(name: "bySpendleeId", fields: ["spendleeId"], queryField: "profilesBySpendleeId")
  @auth(
    rules: [
      { allow: public, provider: apiKey }
      { allow: owner, ownerField: "username" }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID! # username
  username: ID!
  state: String
  spendleeId: String!
  avatarImage: String
  scansPerDay: Int
}

enum SpendSummaryType {
  YEAR
  MONTH
  WEEK
  DAY
}

enum SpendSummaryState {
  REQUESTED
  PROCESSING
  ERROR
  DONE
}

type SpendSummary3
  @model
  @key(name: "byUsername", fields: ["username"], queryField: "spendSummary3sByUsername")
  @auth(
    rules: [
      { allow: public, provider: apiKey }
      { allow: owner, ownerField: "username" }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID!
  username: ID!
  type: String!
  year: String!
  month: String
  day: String
  state: String!
  error: String
  total: Float
  numberOfReceipts: Int
  _ttl: Float
}

type EventType
  @model
  @key(name: "byEventName", fields: ["name"], queryField: "eventTypeByName")
  @auth(
    rules: [
      { allow: public, provider: apiKey }
      { allow: owner, ownerField: "username" }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID!
  username: ID
  name: String!
  description: String
  subscribers: String
}

type DailyScan
  @model
  @key(name: "byDateAndUser", fields: ["date", "username"], queryField: "scansByNameAndDate")
  @auth(
    rules: [
      { allow: public, provider: apiKey }
      { allow: owner, ownerField: "username" }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID!
  date: AWSDateTime
  username: ID
  currentScansPerDayLimit: Int! # limit which was active on that date
  currentDayScans: Int! # scans done on that day so far
}

type OverLimitDailyScans
  @model
  @auth(
    rules: [
      { allow: public, provider: apiKey }
      { allow: owner, ownerField: "username" }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID!
  username: ID!
}

type ThirdPartyApi
  @model
  @key(name: "byApiName", fields: ["name"], queryField: "apiByName")
  @auth(
    rules: [
      { allow: public, provider: apiKey }
      { allow: owner, ownerField: "username" }
      { allow: groups, groups: ["appadmin"], operations: [create, update, read, delete] }
    ]
  ) {
  id: ID!
  username: ID
  name: String! # URL domain?
  description: String
  billingPeriodDays: Int!
  billingPeriodStartDate: AWSDateTime!
  maxCallsPerBillingPeriod: Int # optional?
  threshold: Float
  notificationSent: Boolean! # reset it monthly! false if threshold == 0
  billingPeriodBeginningBalance: Int # balance in number of calls
  currentBillingPeriodCalls: Int # reset every billing to 0
}

Here's my amplifyconfiguration.json:

{
    "UserAgent": "aws-amplify-cli/2.0",
    "Version": "1.0",
    "api": {
        "plugins": {
            "awsAPIPlugin": {
                "spendleeenveapi": {
                    "endpointType": "GraphQL",
                    "endpoint": "https://REDACTED_BY_JAMESON.appsync-api.us-east-1.amazonaws.com/graphql",
                    "region": "us-east-1",
                    "authorizationType": "AMAZON_COGNITO_USER_POOLS"
                }
            }
        }
    },
    "auth": {
        "plugins": {
            "awsCognitoAuthPlugin": {
                "UserAgent": "aws-amplify/cli",
                "Version": "0.1.0",
                "IdentityManager": {
                    "Default": {}
                },
                "CredentialsProvider": {
                    "CognitoIdentity": {
                        "Default": {
                            "PoolId": "us-east-1:REDACTED_BY_JAMESON",
                            "Region": "us-east-1"
                        }
                    }
                },
                "CognitoUserPool": {
                    "Default": {
                        "PoolId": "us-east-1_REDACTED_BY_JAMESON",
                        "AppClientId": "xxxxxxxxxxxxxxxxxxxxxxxxx",
                        "AppClientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                        "Region": "us-east-1"
                    }
                },
                "Auth": {
                    "Default": {
                        "authenticationFlowType": "USER_SRP_AUTH"
                    }
                },
                "S3TransferUtility": {
                    "Default": {
                        "Bucket": "REDACTED_BY_JAMESON",
                        "Region": "us-east-1"
                    }
                },
                "AppSync": {
                    "Default": {
                        "ApiUrl": "https://REDACTED_BY_JAMESON.appsync-api.us-east-1.amazonaws.com/graphql",
                        "Region": "us-east-1",
                        "AuthMode": "AMAZON_COGNITO_USER_POOLS",
                        "ClientDatabasePrefix": "spendleeenveapi_AMAZON_COGNITO_USER_POOLS"
                    }
                },
                "PinpointAnalytics": {
                    "Default": {
                        "AppId": "REDACTED_BY_JAMESON",
                        "Region": "us-east-1"
                    }
                },
                "PinpointTargeting": {
                    "Default": {
                        "Region": "us-east-1"
                    }
                }
            }
        }
    },
    "storage": {
        "plugins": {
            "awsS3StoragePlugin": {
                "bucket": "REDACTED_BY_JAMESON",
                "region": "us-east-1",
                "defaultAccessLevel": "guest"
            }
        }
    },
    "analytics": {
        "plugins": {
            "awsPinpointAnalyticsPlugin": {
                "pinpointAnalytics": {
                    "appId": "REDACTED_BY_JAMESON",
                    "region": "us-east-1"
                },
                "pinpointTargeting": {
                    "region": "us-east-1"
                }
            }
        }
    }
}

Here are some additional logs:

2020-09-17 14:44:48.499 11787-11787/com.spendlee.dev I/first聽Initialization: Initialized Amplify
2020-09-17 14:44:53.268 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: PersistentModelVersion
2020-09-17 14:44:53.334 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: LastSyncMetadata
2020-09-17 14:44:53.408 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: ModelMetadata
2020-09-17 14:44:53.483 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: PersistentRecord
2020-09-17 14:44:53.571 11787-11935/com.spendlee.dev I/amplify:aws-datastore: DataStore orchestrator transitioning states. Current mode = STOPPED, target mode = LOCAL_ONLY.
2020-09-17 14:44:53.574 11787-11935/com.spendlee.dev I/amplify:aws-datastore: Starting to observe local storage changes.
2020-09-17 14:44:53.586 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: SpendSummary3
2020-09-17 14:44:53.707 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: LogEntry
2020-09-17 14:44:53.831 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: Profile
2020-09-17 14:44:53.979 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: Receipt
2020-09-17 14:44:54.117 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating index for table: LogEntry
2020-09-17 14:44:54.244 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating index for table: PersistentRecord
2020-09-17 14:44:54.368 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating index for table: SpendSummary3
2020-09-17 14:44:54.799 11787-11935/com.spendlee.dev W/amplify:aws-datastore: Failed to start observing storage changes.
2020-09-17 14:44:54.833 11787-11944/com.spendlee.dev D/amplify:aws-datastore: Orchestrator completed a transition
2020-09-17 14:44:54.891 11787-11943/com.spendlee.dev D/amplify:aws-datastore: Querying item for: PersistentModelVersion
2020-09-17 14:44:55.097 11787-11936/com.spendlee.dev D/amplify:aws-datastore: Writing data to table for: PersistentModelVersion{id='1ae1b4d0-7894-4f23-831e-ccf6c8439e1c', version='643d6e39-8eb6-3709-8fcd-bbd175ecebc2'}
2020-09-17 14:44:55.329 11787-11936/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = 1ae1b4d0-7894-4f23-831e-ccf6c8439e1c
2020-09-17 14:44:55.343 11787-11936/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = 643d6e39-8eb6-3709-8fcd-bbd175ecebc2
2020-09-17 14:44:48.499 11787-11787/com.spendlee.dev I/first聽Initialization: Initialized Amplify
2020-09-17 14:44:53.268 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: PersistentModelVersion
2020-09-17 14:44:53.334 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: LastSyncMetadata
2020-09-17 14:44:53.408 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: ModelMetadata
2020-09-17 14:44:53.483 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: PersistentRecord
2020-09-17 14:44:53.571 11787-11935/com.spendlee.dev I/amplify:aws-datastore: DataStore orchestrator transitioning states. Current mode = STOPPED, target mode = LOCAL_ONLY.
2020-09-17 14:44:53.574 11787-11935/com.spendlee.dev I/amplify:aws-datastore: Starting to observe local storage changes.
2020-09-17 14:44:53.586 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: SpendSummary3
2020-09-17 14:44:53.707 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: LogEntry
2020-09-17 14:44:53.831 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: Profile
2020-09-17 14:44:53.979 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating table: Receipt
2020-09-17 14:44:54.117 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating index for table: LogEntry
2020-09-17 14:44:54.244 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating index for table: PersistentRecord
2020-09-17 14:44:54.368 11787-11936/com.spendlee.dev I/amplify:aws-datastore: Creating index for table: SpendSummary3
2020-09-17 14:44:54.799 11787-11935/com.spendlee.dev W/amplify:aws-datastore: Failed to start observing storage changes.
    java.lang.RuntimeException: AmplifyException {message=Error in querying the model., cause=java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.Cursor android.database.sqlite.SQLiteDatabase.rawQuery(java.lang.String, java.lang.String[])' on a null object reference, recoverySuggestion=See attached exception for details.}
        at io.reactivex.rxjava3.internal.util.ExceptionHelper.wrapOrThrow(ExceptionHelper.java:46)
        at io.reactivex.rxjava3.internal.observers.BlockingMultiObserver.blockingAwait(BlockingMultiObserver.java:145)
        at io.reactivex.rxjava3.core.Completable.blockingAwait(Completable.java:1490)
        at com.amplifyframework.datastore.syncengine.Orchestrator.startObservingStorageChanges(Orchestrator.java:248)
        at com.amplifyframework.datastore.syncengine.Orchestrator.transitionToLocalOnly(Orchestrator.java:212)
        at com.amplifyframework.datastore.syncengine.Orchestrator.transitionCompletable(Orchestrator.java:169)
        at com.amplifyframework.datastore.syncengine.Orchestrator.start(Orchestrator.java:139)
        at com.amplifyframework.datastore.AWSDataStorePlugin.initialize(AWSDataStorePlugin.java:226)
        at com.amplifyframework.core.category.Category.initialize(Category.java:120)
        at com.amplifyframework.core.Amplify.lambda$beginInitialization$0(Amplify.java:163)
        at com.amplifyframework.core.-$$Lambda$Amplify$EB8h7rBH19uqUcPr0ZtYS0ww0r4.run(Unknown Source:4)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
     Caused by: AmplifyException {message=Error in querying the model., cause=java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.Cursor android.database.sqlite.SQLiteDatabase.rawQuery(java.lang.String, java.lang.String[])' on a null object reference, recoverySuggestion=See attached exception for details.}
        at com.amplifyframework.datastore.storage.sqlite.SQLiteStorageAdapter.lambda$query$4$SQLiteStorageAdapter(SQLiteStorageAdapter.java:397)
        at com.amplifyframework.datastore.storage.sqlite.-$$Lambda$SQLiteStorageAdapter$rGner20-W7t2tJu4yCrrZwlquWE.run(Unknown Source:10)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)聽
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)聽
        at java.lang.Thread.run(Thread.java:919)聽
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.Cursor android.database.sqlite.SQLiteDatabase.rawQuery(java.lang.String, java.lang.String[])' on a null object reference
        at com.amplifyframework.datastore.storage.sqlite.SQLiteStorageAdapter.getQueryAllCursor(SQLiteStorageAdapter.java:794)
        at com.amplifyframework.datastore.storage.sqlite.SQLiteStorageAdapter.lambda$query$4$SQLiteStorageAdapter(SQLiteStorageAdapter.java:372)
        at com.amplifyframework.datastore.storage.sqlite.-$$Lambda$SQLiteStorageAdapter$rGner20-W7t2tJu4yCrrZwlquWE.run(Unknown Source:10)聽
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)聽
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)聽
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)聽
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)聽
        at java.lang.Thread.run(Thread.java:919)聽
2020-09-17 14:44:54.833 11787-11944/com.spendlee.dev D/amplify:aws-datastore: Orchestrator completed a transition
2020-09-17 14:44:54.891 11787-11943/com.spendlee.dev D/amplify:aws-datastore: Querying item for: PersistentModelVersion
2020-09-17 14:44:55.097 11787-11936/com.spendlee.dev D/amplify:aws-datastore: Writing data to table for: PersistentModelVersion{id='1ae1b4d0-7894-4f23-831e-ccf6c8439e1c', version='643d6e39-8eb6-3709-8fcd-bbd175ecebc2'}
2020-09-17 14:44:55.329 11787-11936/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = 1ae1b4d0-7894-4f23-831e-ccf6c8439e1c
2020-09-17 14:44:55.343 11787-11936/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = 643d6e39-8eb6-3709-8fcd-bbd175ecebc2
2020-09-17 14:46:59.981 11787-12373/com.spendlee.dev W/om.spendlee.de: Verification of void com.spendlee.dev.viewModels.AuthViewModel$callAuthSession$1$1.accept(com.amplifyframework.auth.AuthSession) took 145.547ms
2020-09-17 14:47:00.721 11787-12373/com.spendlee.dev I/amplify:aws-datastore: DataStore orchestrator transitioning states. Current mode = STOPPED, target mode = LOCAL_ONLY.
2020-09-17 14:47:00.721 11787-12373/com.spendlee.dev I/amplify:aws-datastore: Starting to observe local storage changes.
2020-09-17 14:47:00.738 11787-12685/com.spendlee.dev D/amplify:aws-datastore: Querying item for: PersistentRecord
2020-09-17 14:47:00.782 11787-12685/com.spendlee.dev I/amplify:aws-datastore: Now observing local storage. Local changes will be enqueued to mutation outbox.
2020-09-17 14:47:00.785 11787-11944/com.spendlee.dev D/amplify:aws-datastore: Orchestrator completed a transition
2020-09-17 14:47:00.797 11787-12685/com.spendlee.dev D/amplify:aws-datastore: Querying item for: Profile
2020-09-17 14:47:00.801 11787-11944/com.spendlee.dev D/amplify:aws-datastore: Orchestrator completed a transition
2020-09-17 14:47:00.812 11787-12686/com.spendlee.dev D/amplify:aws-datastore: Writing data to table for: Profile {id=3b2fac96-ea30-40c3-81bb-d1e3f7fd263d, username=3b2fac96-ea30-40c3-81bb-d1e3f7fd263d, state=OK, spendleeId=azadehsoli+logger, avatarImage=null, scansPerDay=null}
2020-09-17 14:47:00.816 11787-12686/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = 3b2fac96-ea30-40c3-81bb-d1e3f7fd263d
2020-09-17 14:47:00.816 11787-12686/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = null
2020-09-17 14:47:00.817 11787-12686/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = null
2020-09-17 14:47:00.817 11787-12686/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = azadehsoli+logger
2020-09-17 14:47:00.817 11787-12686/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = OK
2020-09-17 14:47:00.818 11787-12686/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = 3b2fac96-ea30-40c3-81bb-d1e3f7fd263d
2020-09-17 14:47:00.883 11787-12685/com.spendlee.dev D/amplify:aws-datastore: Writing data to table for: Record{id='2bd9012b-f916-11ea-a000-2171c644ddc6', containedModelId='3b2fac96-ea30-40c3-81bb-d1e3f7fd263d', serializedMutationData='{"classOfMutatedItem":"com.amplifyframework.datastore.generated.model.Profile","mutatedItem":{"id":"3b2fac96-ea30-40c3-81bb-d1e3f7fd263d","spendleeId":"azadehsoli+logger","state":"OK","username":"3b2fac96-ea30-40c3-81bb-d1e3f7fd263d"},"mutationId":2bd9012b-f916-11ea-a000-2171c644ddc6,"mutationType":"CREATE","predicate":{"_type":"ALL"}}', containedModelClassName='com.amplifyframework.datastore.generated.model.Profile'}
2020-09-17 14:47:00.886 11787-12685/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = 2bd9012b-f916-11ea-a000-2171c644ddc6
2020-09-17 14:47:00.892 11787-12685/com.spendlee.dev V/amplify:aws-datastore: Could not find getContainedModelClassName() on com.amplifyframework.datastore.syncengine.PendingMutation$PersistentRecord. Fallback to direct field access.
2020-09-17 14:47:00.893 11787-12685/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = com.amplifyframework.datastore.generated.model.Profile
2020-09-17 14:47:00.895 11787-12685/com.spendlee.dev V/amplify:aws-datastore: Could not find getContainedModelId() on com.amplifyframework.datastore.syncengine.PendingMutation$PersistentRecord. Fallback to direct field access.
2020-09-17 14:47:00.895 11787-12685/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = 3b2fac96-ea30-40c3-81bb-d1e3f7fd263d
2020-09-17 14:47:00.898 11787-12685/com.spendlee.dev V/amplify:aws-datastore: Could not find getSerializedMutationData() on com.amplifyframework.datastore.syncengine.PendingMutation$PersistentRecord. Fallback to direct field access.
2020-09-17 14:47:00.898 11787-12685/com.spendlee.dev V/amplify:aws-datastore: SQLiteStorageAdapter.bindValueToStatement(..., value = {"classOfMutatedItem":"com.amplifyframework.datastore.generated.model.Profile","mutatedItem":{"id":"3b2fac96-ea30-40c3-81bb-d1e3f7fd263d","spendleeId":"azadehsoli+logger","state":"OK","username":"3b2fac96-ea30-40c3-81bb-d1e3f7fd263d"},"mutationId":2bd9012b-f916-11ea-a000-2171c644ddc6,"mutationType":"CREATE","predicate":{"_type":"ALL"}}
2020-09-17 14:47:00.904 11787-12685/com.spendlee.dev I/amplify:aws-datastore: Successfully enqueued PendingMutation{mutatedItem=Profile {id=3b2fac96-ea30-40c3-81bb-d1e3f7fd263d, username=3b2fac96-ea30-40c3-81bb-d1e3f7fd263d, state=OK, spendleeId=azadehsoli+logger, avatarImage=null, scansPerDay=null}, classOfMutatedItem=class com.amplifyframework.datastore.generated.model.Profile, mutationType=CREATE, mutationId=2bd9012b-f916-11ea-a000-2171c644ddc6, predicate=MatchAllQueryPredicate}
Bug Clarification Needed Closing Soon DataStore

All 16 comments

Thanks @azisoli! This looks like a bug, to me:

     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.Cursor android.database.sqlite.SQLiteDatabase.rawQuery(java.lang.String, java.lang.String[])' on a null object reference
        at com.amplifyframework.datastore.storage.sqlite.SQLiteStorageAdapter.getQueryAllCursor(SQLiteStorageAdapter.java:794)
        at com.amplifyframework.datastore.storage.sqlite.SQLiteStorageAdapter.lambda$query$4$SQLiteStorageAdapter(SQLiteStorageAdapter.java:372)
        at com.amplifyframework.datastore.storage.sqlite.-$$Lambda$SQLiteStorageAdapter$rGner20-W7t2tJu4yCrrZwlquWE.run(Unknown Source:10) 
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462) 
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:919) 

@jamesonwilliams yes it seems a bug.

Hi @azisoli, in the code sample above, I see this line is commented out:

//  Amplify.addPlugin(AWSApiPlugin())

Without the AWSApiPlugin(), DataStore will operate in a local only mode, so it won't be syncing to the backend. If you uncomment that, it should sync to the backend.

@richardmcclellan i did it and i have this now but still no chnges in database it just change version but not the other fields . log is attached.
lasone.txt

Amplify.addPlugin(AWSCognitoAuthPlugin())
Amplify.addPlugin(AWSApiPlugin())
Amplify.addPlugin(AndroidLoggingPlugin(LogLevel.VERBOSE))
Amplify.addPlugin(AWSDataStorePlugin())
Amplify.addPlugin(AWSS3StoragePlugin())
Amplify.configure(applicationContext)

Hey @azisoli, given that your models are protected with the @auth directive, the initial DataStore initialization fails if no one is signed in yet, as seen in your logs. This is expected, but there are a couple tricks to making sure that DataStore gets re-initialized after sign in. I would suggest doing the following steps:

  1. Sign in
  2. Call DataStore.query to trigger reinitialization of the DataStore, but ignore the results
  3. Wait for the READY Hub event.
  4. Proceed to use DataStore.query/save/observe however you need to.

Here's some sample code for doing this:

Amplify.Auth.signIn(USERNAME, PASSWORD, (AuthSignInResult result) -> {
      Amplify.DataStore.query(Todo.class, result -> { /* ignore this result */ }, error -> { });        
      Amplify.Hub.subscribe(HubChannel.DATASTORE, 
                hubEvent -> DataStoreChannelEventName.READY.equals(hubEvent.getName()), 
                hubEvent -> Amplify.DataStore.query(Todo.class, result -> { /* expect the actual results here */ }, error -> { })
      );
});

In regards to the error that @jamesonwilliams called out:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.Cursor android.database.sqlite.SQLiteDatabase.rawQuery(java.lang.String, java.lang.String[])' on a null object reference

I suspect we might have a bug caused by calling DataStore.save before DataStore is fully initialized. Waiting for the READY hub event as described may resolve this issue.

In the future, we'll consider ways to improve this, so there aren't so many steps required.

@richardmcclellan i need to call Amplify.Auth.fetchAuthSession after signin ,can i call it in hub event and in result of that i call save on datastore?

@richardmcclellan How is this code suppose to work? For me, the first part is happening:

hubEvent -> DataStoreChannelEventName.READY.equals(hubEvent.getName()),

But the second part never happens:

hubEvent -> Amplify.DataStore.query(Todo.class, result -> { /* expect the actual results here */ }, error -> { })

Here are my logs: hub.txt

@azisoli It sounds like DataStoreChannelEventName.READY.equals(hubEvent.getName()) is evaluating to false. This will occur if there are events on the Hub, but none of them are the READY event. Or, in other words, your DataStore instance is never becoming ready.

It shows as ready:

IMG_20200918_123849

Here's my code. Does it look right?

private fun callSignIn(userName: String, password: String) {
    viewModelScope.launch(Dispatchers.IO) {
        Amplify.Auth.signIn(userName, password,
            { result ->
                //signInRes.postValue(ResponseHelper.success(result.isSignInComplete))
                Amplify.DataStore.query(Profile::class.java,{},{})
                Amplify.Hub.subscribe(
                    HubChannel.DATASTORE,
                    { hubEvent ->
                        DataStoreChannelEventName.READY.equals(hubEvent.name) },
                    { hubEvent->
                        Amplify.Auth.fetchAuthSession(
                        { result ->
                            val cognitoAuthSession = result as AWSCognitoAuthSession
                            when (cognitoAuthSession.identityId.type) {
                                AuthSessionResult.Type.SUCCESS -> {
                                    val place = userName.indexOf("@")
                                    val spendIee: String = userName.substring(0, place )
                                    createProfile(cognitoAuthSession.userSub.value.toString(),spendIee,
                                        ProfileState.OK.toString())
                                }
                                AuthSessionResult.Type.FAILURE ->resCreateProfile.postValue(ResponseHelper.error("problem happened in sigIn process", null))
                            }
                        },
                        { error ->  resCreateProfile.postValue(ResponseHelper.error("problem happened in sigIn process", null)) })
                    }

                )
            },
            { error ->
                resCreateProfile.postValue(ResponseHelper.error("problem happened in sigIn process", null)) }
        )
    }
}

@azisoli @richardmcclellan Oh, derp. We're comparing a String to an enum.

This line:

DataStoreChannelEventName.READY.equals(hubEvent.getName())

Needs to become:

DataStoreChannelEventName.READY.toString().equals(hubEvent.getName())

@azisoli @richardmcclellan @rjuliano Where did we end up on this one? Sounds like maybe a combination of https://github.com/aws-amplify/amplify-android/issues/853, and the need to wait for sign-in, via Hub?

We're tracking two fixes that appear to be related to issues reported here.

1 - #853: Adding some safeguards around sync engine startup. This addresses the issue where the startup sequence is getting triggered multiple times.
2 - #854: Derive the subscription startup timeout from the number of models. Currently, the subscription initialization may timeout because it doesn't take into account the number of models in the schema.

Both of these prevent the sync process from pushing local updates to the cloud and pulling cloud updates to local

@rjuliano Awesome! Shall we close this one, and focus on #853 #854? @azisoli does that sound like a plan?

Yes sure

I'm running into the same issue. All versions starting from 1.3.0 and up are causing issues. If I checked correctly, above mentioned issues are not released ? Can I see when this is planned to be released ?

Thanks

@woutermilants This issue has been closed. Can you please open a new issue with details about your code, configuration, and specific errors, with associated logs. Please follow up on #853 and #854 if you are encountering the specific errors referenced in those issues.

Was this page helpful?
0 / 5 - 0 ratings