Sync Geodatabase Issues

2667
3
09-14-2016 08:29 PM
JoshuaDonato
New Contributor

Greetings!

Working on my first Qt app but have not been able to get past the first basic steps. For the app I have a feature service with two layers, layer 0 is for device location (points) and layer 1 is for service areas (polygons). I want to sync service areas from the server to the device (SyncDirectionDownload) and sync device location from the device to the server (SyncDirectionUpload ). I am expecting upon initial sync to the geodatabase, the service areas should be downloaded to the device's geodatabase, but this is not the case. I have tried a few different ways but either no features are downloaded or there are errors.  Any input on what I am doing wrong or if I need to go about this a different way is greatly appreciated!

Thanks,

Josh

Each step is connected to separate buttons. Here is the output for each button:

getServiceButton:
(onFeatureServiceInfoStatusChanged): qml: capabilities: Create,Delete,Query,Sync,Update,Uploads,Editing
(onFeatureServiceInfoStatusChanged): qml: max record count: 1000
(onFeatureServiceInfoStatusChanged): qml: sync enabled?: true
(onFeatureServiceInfoStatusChanged): qml: server version: 10.41

generateButton:
(onClicked): qml: Generating geodatabase...
(onGenerateStatusChanged): qml: Generate geodatabase in progress...
(onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
(onGenerateStatusChanged): qml: Generate geodatabase complete.
(onGenerateStatusChanged): qml: path: data/localdata.geodatabase
(onGenerateStatusChanged): qml: sync enabled: true
(onGenerateStatusChanged): qml: sync model: 1
(onGenerateStatusChanged): qml: valid: true

registerButton:   not sure if this is functioning properly
(onClicked): qml: Registering geodatabase...
(onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0

syncButton:   will error
(onClicked): qml: Syncing geodatabase...
(onSyncStatusChanged): qml: Sync geodatabase in progress...
(onSyncStatusChanged): qml: Error: Invalid or missing input parameters. code= 400 Replica with this GUID does not exist on the server
(onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
(onSyncStatusChanged): qml: Error: Protocol "" is unknown code= 301 Protocol "" is unknown
(onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
(onSyncStatusChanged): qml: Error: Protocol "" is unknown code= 301 Protocol "" is unknown
(onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
(onSyncStatusChanged): qml: Error: Sync failed. Unable to import changes to server. code= -1


Info from the feature server:

Sync Capabilities:
Supports Registering Existing Data: true
Supports Sync Direction Control: true
Supports PerLayer Sync: true
Supports PerReplica Sync: false
Supports RollbackOnFailure : false
Supports Async: true

Supports ApplyEdits With Global Ids: true

Child Resources: Info Uploads Replicas

Supported Operations: Query Apply Edits Create Replica Synchronize Replica Unregister Replica


The code snippet below is what I believe is the closest to what I need (my apologies on the formatting from copy/paste), but it will error when trying to sync.


import QtQuick 2.3
import QtQuick.Controls 1.2
import QtPositioning 5.2

import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.2

import ArcGIS.Runtime 10.26

ApplicationWindow {
id: appWindow
width: 800
height: 600
title: "my cool app"

property string featureServerUrl: // ** url left out on purpose**
property string gdbPath: "data/localdata.geodatabase"

Envelope {
id: env
xMin: -100
xMax: -85
yMin: 40
yMax: 50
}

SpatialReference{
id: sr
wkid: 4326
}

ServiceInfoTask {
id: featureServiceInfoTask
url: featureServerUrl

onFeatureServiceInfoStatusChanged: {

if (featureServiceInfoStatus === Enums.FeatureServiceInfoStatusReady) {
console.log("Fetch feature server info ready...")
}

else if (featureServiceInfoStatus === Enums.FeatureServiceInfoStatusInProgress) {
console.log("Fetch feature server info in progress...")
}

else if (featureServiceInfoStatus === Enums.FeatureServiceInfoStatusCompleted) {
Enums.FeatureServiceInfoStatusErrored
Enums.FeatureServiceInfoStatusInProgress
Enums.FeatureServiceInfoStatusReady
var featureServiceInfo = featureServiceInfoTask.featureServiceInfo
console.log("capabilities:", featureServiceInfo.capabilities)
console.log("max record count:",
featureServiceInfo.maximumRecordCount)
console.log("sync enabled?:", featureServiceInfo.isSyncEnabled)
console.log("server version:", featureServiceInfo.version)
}

else if (featureServiceInfoStatus === Enums.FeatureServiceInfoStatusErrored) {
console.log("Fetch feature server info ERRORED...")
}
}
}

GenerateGeodatabaseParameters {
id: generateGeodatabaseParameters
extent: env
layerIds: [0, 1]
syncModel: Enums.SyncModelLayer
outSpatialReference: sr
}

LayerSyncInfo {
id: layerSyncInfoPoints
layerId: 0
syncDirection: Enums.SyncDirectionUpload
}

LayerSyncInfo {
id: layerSyncInfoPolygons
layerId: 1
syncDirection: Enums.SyncDirectionDownload
}

SyncGeodatabaseParameters {
id: syncGeodatabaseParameters
layerSyncInfos: [layerSyncInfoPoints, layerSyncInfoPolygons]
}

Geodatabase {
id: gdb
path: gdbPath
}

GeodatabaseSyncStatusInfo {
id: geodatabaseSyncStatusInfo
}

GeodatabaseSyncTask {
id: geodatabaseSyncTask
url: featureServerUrl

onGenerateStatusChanged: {

// generate in progress
if (generateStatus === Enums.GenerateStatusInProgress) {
console.log("Generate geodatabase in progress...")
}

// generate complete
else if (generateStatus === Enums.GenerateStatusCompleted) {
console.log("Generate geodatabase complete.")
console.log("path: " + gdb.path)
console.log("sync enabled: " + gdb.isSyncEnabled)
console.log("sync model: " + gdb.syncModel)
console.log("valid: " + gdb.valid)
}

// generate error
else if (generateStatus === GeodatabaseSyncTask.GenerateError) {
console.log("Error: " + generateGeodatabaseError.message
+ " Code= " + generateGeodatabaseError.code.toString(
) + " " + generateGeodatabaseError.details)
}
}

onSyncStatusChanged: {

// sync is ready
if (syncStatus === Enums.SyncStatusReady) {
console.log('Sync geodatabase ready...')
}

// sync in progress
if (syncStatus === Enums.SyncStatusInProgress) {
console.log('Sync geodatabase in progress...')
}

// sync complete
else if (syncStatus === Enums.SyncStatusCompleted) {
console.log("Sync Geodatabase Complete.")
var gdbtables = gdb.geodatabaseFeatureTables
for (var i in gdbtables) {
var geodatabaseFeatureTable = gdbtables
console.log(geodatabaseFeatureTable.featureServiceLayerName)
;
console.log(geodatabaseFeatureTable.features.length)
}
}

// sync error
else if (syncStatus === Enums.SyncStatusErrored) {
console.log("Error: " + syncGeodatabaseError.message + " code= "
+ syncGeodatabaseError.code.toString(
) + " " + syncGeodatabaseError.details)
}
}

onGeodatabaseSyncStatusInfoChanged: {

// uploading status
if (geodatabaseSyncStatusInfo.status === Enums.GeodatabaseStatusUploadingDelta) {
var deltaProgress = geodatabaseSyncStatusInfo.deltaUploadProgress / 1000
var deltaSize = geodatabaseSyncStatusInfo.deltaSize / 1000
console.log(geodatabaseSyncStatusInfo.statusString + " " + String(
deltaProgress) + " of " + String(
deltaSize) + " KBs...")
}

else{
console.log("Sync status: " + geodatabaseSyncStatusInfo.status)
}
}
}

Column {
id: controlsColumn
width: 800
height: 600
anchors.leftMargin: 0
anchors.topMargin: 0
anchors {
left: parent.left
top: parent.top
margins: 20
}
spacing: 7


Button {
id: getServiceButton
text: "Get Service Info"
enabled: true

onClicked: {
console.log("Getting service info...")
featureServiceInfoTask.fetchFeatureServiceInfo()
console.log(featureServiceInfoTask)
}
}

Button {
id: generateButton
text: "Generate Database"
enabled: true

onClicked: {
generateGeodatabaseParameters.initialize(featureServiceInfoTask.featureServiceInfo)
generateGeodatabaseParameters.extent = env
generateGeodatabaseParameters.returnAttachments = false

console.log("Generating geodatabase...")
geodatabaseSyncTask.generateGeodatabase(generateGeodatabaseParameters, gdbPath)
}
}


Button {
id: registerButton
text: "Register Database"
enabled: true

onClicked: {
// register geodatabase
console.log("Registering geodatabase...")
geodatabaseSyncTask.registerGeodatabase(gdb)
}
}

Button {
id: syncButton
text: "Sync Database"
enabled: true

onClicked: {

console.log("Syncing geodatabase...")
geodatabaseSyncTask.syncGeodatabase(
syncGeodatabaseParameters, gdb)
}
}
}
}

0 Kudos
3 Replies
LucasDanzinger
Esri Frequent Contributor

Hey Joshua-

I tried your code with this feature service URL (http://sampleserver6.arcgisonline.com/arcgis/rest/services/Sync/WildfireSync/FeatureServer), and when I inspect the output geodatabase file, I see all of the layers in it. When you say it doesn't bring down your service layer polygons, how are you verifying this? Are you looking at the table in some sqlite browser? Or are you adding the output to a map?

Thanks,

Luke

0 Kudos
JoshuaDonato
New Contributor

Hi Luke,

Thanks for the response. Its been a while but I am finally back on this project. I think I was not completely understanding what some of the classes actually do and how to properly accomplish my task and found myself going in circles in the API docs. Here is a (long winded) description of what I am trying to do.

I am trying to pull down all polygons from a layer in a service onto a device when the application starts up. I am expecting intermittent data connection but I need to have access to the polygons at all times. Plus I want to minimize data traffic because the client is concerned about the data plan. Ideally, the data would persist on the device in case there is no data connection when the app starts. When a data connection is made, any updates to the polygon layer on the service would also be updated on the device. The app will not make changes to the polygon data, the polygons simply need to be on the device at all times.

I also need to generate point data on the device indicating the device location and what polygon it is in. Again, since I am expecting intermittent data connection, the point data needs to persist in a local geodatabase if there is no connection and sent to the service when there is a connection.

I think the code I posted is a start but is missing some parts. I believe a query is required to pull all the polygon data into a geodatabase to save it to disk but I am not sure where that needs to occur. I think I saw a post you responded to regarding this but have not been able to find it again. As for updating the polygon layer in the local geodatabase and pushing any points in the geodatabase to the service, I am not sure if syncing is the correct methodology.

Any pointers you have are greatly appreciated.

Thanks,

Josh

0 Kudos
JoshuaDonato
New Contributor

I added more lines of output to see what is happening in some of the steps.  I am logging what layers are in the local geodatabase and the feature count for the layers after generation.  

Using the WildfireSync data, I am trying to pull all the features from the service to the local geodatabase.  The log indicates each layer is in the local geodatabase, but each layer has no features.  When syncing, it errors indicating no Replica GUID.  When viewing .../WildfireSync/FeatureServer/replicas I can see that a replica is being created along with a Replica ID.  The output JSON string for geodatabase sync status info does not have a replica id or replica name.  All this is the same for my own service.

I'm at a loss as to why I cannot replicate a geodatabase on my device.

Any insight is much appreciated.

#####  Logging Info #####

Click Get Service Info:

D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:226 (onClicked): qml: Getting service info...
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:228 (onClicked): qml: QmlServiceInfoTask(0xb901aaa0)
D/libc-netbsd(21456): [getaddrinfo]: hostname=xxxxx; servname=(null); cache_mode=(null), netid=0; mark=0
D/libc-netbsd(21456): [getaddrinfo]: ai_addrlen=0; ai_canonname=xxxxx; ai_flags=1024; ai_family=0
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:44 (onFeatureServiceInfoStatusChanged): qml: capabilities: Create,Delete,Query,Sync,Update,Uploads,Editing
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:45 (onFeatureServiceInfoStatusChanged): qml: max record count: 1000
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:47 (onFeatureServiceInfoStatusChanged): qml: sync enabled?: true
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:48 (onFeatureServiceInfoStatusChanged): qml: server version: 10.41

Click Register Database:

D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:238 (onClicked): qml: Registering geodatabase...
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:202 (onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:203 (onGeodatabaseSyncStatusInfoChanged): qml: geodatabase sync status info json:{"jobId":null,"lastUpdatedTime":21600000,"replicaID":null,"replicaName":null,"responseType":"esriReplicaResponseTypeData","resultUrl":null,"status":"Pending","submissionTime":21600000,"updateUrl":null}

Click Generate Geodatabase

D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:253 (onClicked): qml: Generating geodatabase...
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:132 (onGenerateStatusChanged): qml: Generate geodatabase in progress...
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:133 (onGenerateStatusChanged): qml: geodatabase sync status info json:{"jobId":null,"lastUpdatedTime":21600000,"replicaID":null,"replicaName":null,"responseType":"esriReplicaResponseTypeData","resultUrl":null,"status":"Pending","submissionTime":21600000,"updateUrl":null}
D/libc-netbsd(21456): [getaddrinfo]: hostname=xxxxx; servname=(null); cache_mode=(null), netid=0; mark=0
D/libc-netbsd(21456): [getaddrinfo]: ai_addrlen=0; ai_canonname=xxxxx; ai_flags=1024; ai_family=0
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:202 (onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:203 (onGeodatabaseSyncStatusInfoChanged): qml: geodatabase sync status info json:{"jobId":null,"lastUpdatedTime":21600000,"replicaID":null,"replicaName":null,"responseType":"esriReplicaResponseTypeData","resultUrl":null,"status":"Pending","submissionTime":21600000,"updateUrl":null}
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:202 (onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:203 (onGeodatabaseSyncStatusInfoChanged): qml: geodatabase sync status info json:{"jobId":null,"lastUpdatedTime":21600000,"replicaID":null,"replicaName":null,"responseType":"esriReplicaResponseTypeData","resultUrl":null,"status":"Pending","submissionTime":21600000,"updateUrl":null}
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:135 (onGenerateStatusChanged): qml: Generate geodatabase complete.
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:136 (onGenerateStatusChanged): qml: geodatabase path: data/localdata.geodatabase
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:137 (onGenerateStatusChanged): qml: geodatabase sync enabled: true
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:138 (onGenerateStatusChanged): qml: geodatabase sync model: 1
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:139 (onGenerateStatusChanged): qml: geodatabase valid: true
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:140 (onGenerateStatusChanged): qml: geodatabase sync task url:https://sampleserver6.arcgisonline.com/arcgis/rest/services/Sync/WildfireSync/FeatureServer
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:142 (onGenerateStatusChanged): qml: geodatabase sync status info json:{"jobId":null,"lastUpdatedTime":21600000,"replicaID":null,"replicaName":null,"responseType":"esriReplicaResponseTypeData","resultUrl":null,"status":"Pending","submissionTime":21600000,"updateUrl":null}
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:146 (onGenerateStatusChanged): qml: table count: 3
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:150 (onGenerateStatusChanged): qml: Table name: Wildfire Response Points
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:151 (onGenerateStatusChanged): qml: Feature count: 0
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:150 (onGenerateStatusChanged): qml: Table name: Wildfire Response Lines
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:151 (onGenerateStatusChanged): qml: Feature count: 0
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:150 (onGenerateStatusChanged): qml: Table name: Wildfire Response Polygons
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:151 (onGenerateStatusChanged): qml: Feature count: 0

Click Sync Geodatabase:

D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:266 (onClicked): qml: Syncing geodatabase...
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:167 (onSyncStatusChanged): qml: Sync geodatabase in progress...
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:183 (onSyncStatusChanged): qml: Error: Invalid or missing input parameters. code= 400 Replica with this GUID does not exist on the server
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:202 (onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:203 (onGeodatabaseSyncStatusInfoChanged): qml: geodatabase sync status info json:{"jobId":null,"lastUpdatedTime":21600000,"replicaID":null,"replicaName":null,"responseType":"esriReplicaResponseTypeData","resultUrl":null,"status":"Pending","submissionTime":21600000,"updateUrl":null}
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:183 (onSyncStatusChanged): qml: Error: Protocol "" is unknown code= 301 Protocol "" is unknown
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:202 (onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:203 (onGeodatabaseSyncStatusInfoChanged): qml: geodatabase sync status info json:{"jobId":null,"lastUpdatedTime":21600000,"replicaID":null,"replicaName":null,"responseType":"esriReplicaResponseTypeData","resultUrl":null,"status":"Pending","submissionTime":21600000,"updateUrl":null}
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:183 (onSyncStatusChanged): qml: Error: Protocol "" is unknown code= 301 Protocol "" is unknown
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:202 (onGeodatabaseSyncStatusInfoChanged): qml: Sync status: 0
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:203 (onGeodatabaseSyncStatusInfoChanged): qml: geodatabase sync status info json:{"jobId":null,"lastUpdatedTime":21600000,"replicaID":null,"replicaName":null,"responseType":"esriReplicaResponseTypeData","resultUrl":null,"status":"Pending","submissionTime":21600000,"updateUrl":null}
D/localGeodatabaseWildfires(21456): qrc:/qml/main.qml:183 (onSyncStatusChanged): qml: Error: Sync failed. Unable to import changes to server. code= -1

0 Kudos