Support Topics Documentation Slack YouTube Blog

Unable to update spatial data point?

I have a table with a column named “location” of type POINT WGS 84. I want to update the value of a single column in a single row in that table. This is my code:

        MapDrivenDataStore *dataStore = [Backendless.shared.data ofTable:[self getSignalsTableName]];
        [dataStore findByIdWithObjectId:signal.signalId responseHandler:^(NSDictionary<NSString *,id> * _Nonnull signalMap) {            
        NSMutableDictionary *updatedSignalMap = [NSMutableDictionary dictionaryWithDictionary:signalMap];
        [updatedSignalMap setObject:[NSNumber numberWithUnsignedInteger:status] forKey:kField_Status];
        [dataStore updateWithEntity:updatedSignalMap
            responseHandler:^(NSDictionary<NSString *,id> * _Nonnull updatedSignal) {
                [self sendPushNotificationsForNewStatus:status onSignal:signal withCurrentComments:currentComments];
                signal.status = status;
                completion(nil);
            } errorHandler:^(Fault * _Nonnull fault) {
                FINError *error = [[FINError alloc] initWithMessage:fault.message];
                completion(error);
            }];
    } errorHandler:^(Fault * _Nonnull fault) {
        FINError *error = [[FINError alloc] initWithMessage:fault.message];
        completion(error);
    }];

However, upon execution I get the following error:

Error Domain=BackendlessErrorDomain Code=0 “Can not create BackendlessGeometry from type weborb.reader.CacheableAdaptingTypeWrapper” UserInfo={NSLocalizedDescription=Can not create BackendlessGeometry from type weborb.reader.CacheableAdaptingTypeWrapper}

If I try to convert the “location” value (which is of type BLPoint) to GeoJSON like this:

    BLPoint *blPoint = [updatedSignalMap objectForKey:kField_Location];
    NSDictionary *jsonPoint = [blPoint asGeoJson];
    [updatedSignalMap setObject:jsonPoint forKey:kField_Location];

I get the same error:

Error Domain=BackendlessErrorDomain Code=0 “Can not create BackendlessGeometry from type weborb.reader.CacheableAdaptingTypeWrapper” UserInfo={NSLocalizedDescription=Can not create BackendlessGeometry from type weborb.reader.CacheableAdaptingTypeWrapper}

Converting to WKT point:

    BLPoint *blPoint = [updatedSignalMap objectForKey:kField_Location];
    NSString *wktPoint = [blPoint asWkt];
    [updatedSignalMap setObject:wktPoint forKey:kField_Location];

returns:

Error Domain=BackendlessErrorDomain Code=0 “Can not create BackendlessGeometry from type weborb.reader.StringType” UserInfo={NSLocalizedDescription=Can not create BackendlessGeometry from type weborb.reader.StringType}

So, how am I supposed to update a table with a spatial data column in it!?
Also, is it possible to update only a single column without sending the rest of the columns in the dictionary? Currently this results in deleting their values.

Hello @milen-marinov

What version of SDK are you using?

Hello,

I’m using BackendlessSwift 6.0

I have also checked the same thing in Android (SDK com.backendless:backendless:6.0.1) where it behaves in the same way.

Hello @milen-marinov

I try to reproduce in Android (SDK com.backendless:backendless:6.0.1):

  1. Create new application.
  2. Create table Table1 (add 2 coulumns: location-Point and name-String)
  3. Add one object to Table1:
{
	"name": "name1",
	"location": {
		"type": "Point",
		"coordinates": [
			11.11,
			22.22
		],
		"srsId": 4326,
		"___class": "com.backendless.persistence.Point"
	}
}
  1. Call from Android:
    Map<String, Object> objectMap = new HashMap<>();
    objectMap.put( "objectId", <objectId> );
    Point point = new Point();
    point.setLongitude( 12.34 );
    point.setLatitude( 56.78 );
    objectMap.put( "location", point );
    Map<String, Object> response = Backendless.Persistence.of( "Table1" ).save( objectMap );
    System.out.println( response );

response:

{created=Mon Sep 14 12:51:26 EEST 2020, name=name1, ___class=Table1, location='POINT(12.34 56.78)', ownerId=null, updated=Mon Sep 14 13:19:07 EEST 2020, objectId=2E0FD1BC-1878-4A3A-88A9-B17BD8C5C7ED}

and in console i see changed object.

Also i test in REST:
PUT
https://api.backendless.com/<appId>/<rest-api-key>/data/Table1/<objectId>

{
	"location":
	{
		"type": "Point",
		"coordinates": [ 10.10, 20.20 ]
	}  
}

response:

{
    "created": 1600077086000,
    "name": "name1",
    "___class": "Table1",
    "location": {
        "type": "Point",
        "coordinates": [
            10.1,
            20.2
        ],
        "srsId": 4326,
        "___class": "com.backendless.persistence.Point"
    },
    "ownerId": null,
    "updated": 1600077927000,
    "objectId": "2E0FD1BC-1878-4A3A-88A9-B17BD8C5C7ED"
}

and in console i see changed object.

Please, provide your Android code with which you have this error.

Hi,

Here is the Android code:

    Backendless.Persistence.of(getTableName()).findById(signalId, new AsyncCallback<Map>() {
        @Override
        public void handleResponse(Map response) {
            response.put(SIGNAL_STATUS, status);

            Backendless.Persistence.of(getTableName()).save(response, new AsyncCallback<Map>() {
                @Override
                public void handleResponse(Map saveResponse) {
                    // Update signal in database
                    //...

                    callback.onStatusUpdated(status);
                }

                @Override
                public void handleFault(BackendlessFault fault) {
                    callback.onStatusFailure(fault.getMessage());
                }
            });
        }

        @Override
        public void handleFault(BackendlessFault fault) {
            callback.onStatusFailure(fault.getMessage());
        }
    });

However, I did some more testing and found that the issue is related to (but not directly caused by) an event handler beforeUpdate that I have for this table. If I disable this event handler everything goes fine. If I enable it the operation fails with the above mentioned errors. However, when I run the event handler in remote debug mode the operation fails before entering the beforeUpdate method. So it looks like the problem is not in my code but somewhere in the cloud code that’s executed before it.

My AppId is BDCD56B9-351A-E067-FFA4-9EA9CF2F4000, the table is SignalsTest, and the event handler is beforeUpdate in the status_update model. As implied by the name the table is for test purposes so you play with it safely.

Best,
Milen

Hello @milen-marinov

I reproduced the issue.
The internal ticket (BKNDLSS-22728) has been created. Your problem will be investigated and fixed as soon as possible.

1 Like

As it is 01.10 and the issue is still not fixed can we get a postponement of the Geoservice deprecation scheduled for 05.10?
Otherwise we will be forced to either release updated apps with regressions (missing features that were present before the update) or not update at all and have the app stop working (or worse - crash, depending on what will happen to the requests to the Geoservice).

Hello @milen-marinov

Yes, we have already begun work to end support for the old Geoservice, but since it will take some more time, you actually get a postponement.
Work on the problem you described is still underway and it may be completed, tested and released before the old Geoservice stops working.

Ok, thanks. How can I get notified about the actual date of deprecation?

Hello @milen-marinov

Unfortunately, there is no such date for the actual termination of support for the work of the old Geoservice.
In fact, this functionality can be removed at any time, interruptions in its work are possible, since all the same, the official date of the end of support remains 05.10.2020.

Sorry, but this is a really bad service!
New functionality is buggy, there is no date for an expected fix, old functionality is being deprecated but not quite and it can stop working at any time…
So what am I to do - migrate my users to Spatial data where they won’t be able to update points on the map (regression) or wait with my fingers crossed, hoping my app won’t stop working suddenly!?
And on top of that I’m receiving this answer 20 days later!

Hello @milen-marinov

Sorry for the long answer, we try to answer all questions as quickly as possible. This could be due to an accident.

I would recommend that you still switch to spatial types. We will do our best to fix this issue as quickly as possible.
I will now double-check this issue and raise the priority from this task.

1 Like

Hello @milen-marinov

We’ve just updated cloud servers with a fix for the issue you described above. Could you kindly let us know whether fix works for you well?

Regards,
Inna

Hi @Inna_Shkolnaya

I tested it and now it’s possible to update without the previous error. However, now there is another problem - when the ‘beforeUpdate’ handler is enabled updating only a single column deletes the values of all other columns! If ‘beforeUpdate’ handler is disabled updating a single column changes only the value of that column.
Here is the code for iOS (tested it also on Android and it behaves the same way):

MapDrivenDataStore *dataStore = [Backendless.shared.data ofTable:[self getSignalsTableName]];
NSMutableDictionary *changes = [NSMutableDictionary new];
[changes setObject:[NSNumber numberWithUnsignedInteger:status] forKey:kField_Status];
[changes setObject:signal.signalId forKey:kField_ObjectId];
[dataStore updateWithEntity:changes
    responseHandler:^(NSDictionary<NSString *,id> * _Nonnull updatedSignal) {
        [self sendPushNotificationsForNewStatus:status onSignal:signal withCurrentComments:currentComments];
        signal.status = status;
        completion(nil);
    } errorHandler:^(Fault * _Nonnull fault) {
        FINError *error = [[FINError alloc] initWithMessage:fault.message];
        completion(error);
    }];

My code in the handler does not change the row that is being updated:

  @Override
  public void beforeUpdate( RunnerContext context, Signals signal ) throws Exception
  {
    // add your code here
    Map oldSignal = Backendless.Data.of("Signals").findById(signal.getObjectId());
    Integer oldStatus = (Integer) oldSignal.get("status");
    if (!oldStatus.equals(signal.getStatus())) {
      HashMap comment = new HashMap();
      comment.put( "text", "{\"old\":" + oldStatus + ",\"new\":" + signal.getStatus() + "}");
      comment.put( "signalID", signal.getObjectId() );
      comment.put( "type", "status_change" );
      Map response = Backendless.Data.of( "FINComment" ).save( comment );
      List users = new ArrayList();
      BackendlessUser user = Backendless.UserService.findById(context.getUserId());
      users.add(user);
      Backendless.Data.of("FINComment").setRelation(response, "author", users);
    }
  }

Hi, @milen-marinov

We investigate your problem. We will write you as there are results on it.

Regards,
Marina

@milen-marinov, I checked your case and found that it caused by bug in handlers arguments typecast logic. We have a ticket for your case - BKNDLSS-23267, it looks like regression. We will notify you when it is fixed. As temporary bypass you can remove mappings for model classes and use Map instances.
Sorry for the inconvenience.

Regards,
Marina

1 Like