Trouble updating relationship from afterCreate

Two classes: Contact and PhoneNumber. Contact has [ Data Relation (1:N): PhoneNumber ]
I’m currently working on importing data over REST and unfortunately I have to make separate table based REST requests. Most of this is working okay, but I have an afterCreate event on the PhoneNumber so that it locates the already imported Contact based on an importId field then associates itself with that contact.
In the code below there are a couple of console.log statements, one before and one after pushing the created PhoneNumber onto the Contact. In the console I can clearly see the before and after results are as expected. However, the save never seems to work as the relationship is not persisted. I’ve also tried the 1 to 1 with the relationship on the PhoneNumber and still can not get it to save the relationships.
phonenumber/afterCreate.js

var Contact = require('../../../models/contact');
var PhoneNumber = require('../../../models/phonenumber');



Backendless.ServerCode.Persistence.afterCreate('PhoneNumber', function(req, res) {
 var dataQuery = new Backendless.DataQuery();
 dataQuery.condition = 'importId = ' + res.result.phoneableId;



 var contactsStore = Backendless.Persistence.of( Contact );
 contactsStore.find( dataQuery )



 .then( results => {
 contact = results.data[0]
 if (contact) {



 console.log(require('util').inspect(contact, { depth: null }));
 contact.phoneNumbers.push(res.result);
 console.log(require('util').inspect(contact, { depth: null }));



return contact.save();
//return contactsStore.save(contact)
 }



 }).catch(err => {
 return Promise.reject('Got an error : ' + err.message)
 });



});

contact.js

class Contact extends Backendless.ServerCode.PersistenceItem {
 constructor() {
 super();
 /**
 @name Contact#importId
 @type Number
 */
 this.importId = undefined;



 /**
 @name Contact#lastName
 @type String
 */
 this.lastName = undefined;



 /**
 @name Contact#phoneNumbers
 @type Array.<PhoneNumber>
 */
 this.phoneNumbers = undefined;



 /**
 @name Contact#firstName
 @type String
 */
 this.firstName = undefined;



 }
}



module.exports = Backendless.ServerCode.addType(Contact);

Hi Chris,

I think the code which saves the updated contact object is never executed. Please see this page in the doc:
https://backendless.com/documentation/business-logic/js/bl_sync_vs_async_code.htm

Regards,
Mark

Good point, and you are right in that code it didn’t. I’ve been through so many permutations trying to get it to work. What led me down that route was trying to resolve the error ‘Cannot save entity with primitive collection property dates’.

This modified version does run, and closely matches the Sync vs Async docs, however it returns the cannot save entity with primitive collection error.

var contactsStore = Backendless.Persistence.of( Contact );
  return contactsStore.find( dataQuery )
    .then( results => {
      contact = results.data[0]
      if (contact) {
        contact.phoneNumbers.push(res.result);
      return contact.save()
    }
  }).catch(err => {
    return Promise.reject('Got an error : ' + err.message)
 });

Could you please check what “res.result” contains? it should be a complete object with objectId and other properties. I’d like to make sure it is indeed that.

Also, what version of CodeRunner do you have?

Looking at the coderunner changelog in my node_modules package it looks to be v1.7.2. This is a Backendless Standalone bitnami VM downloaded yesterday, so it’s pretty recent I believe.

Yes it does appear to be a complete object.

result of inspecting res.result

PhoneNumber {
 ___class: 'PhoneNumber',

 ownerId: null,
 objectId: '64584A32-B847-7E3F-FF5D-427C8836CB00',
 created: '1466629351000',
 updated: null,
 extension: null,
 phoneableType: 'Contact',
 number: '123-123-1234',
 category: 'office',
 phoneableId: 100000,
 importId: 1,
 primary: true,
 ___jsonclass: 'PhoneNumber',
 __meta: '{"relationRemovalIds":{},"selectedProperties":["extension","created","phoneableId","ownerId","phoneableType","number","importId","___saved","___class","category","
updated","objectId","primary"],"relatedObjects":{}}',
 ___dates___: [ '1466629351000' ] }

and the result of inspecting the contact AFTER pushing the res.result onto the array

Contact {

 ___class: 'Contact',
 ownerId: null,
 objectId: 'E3F7D045-CF48-5B51-FF90-30E70CFDDF00',
 created: 1466622722000,
 updated: 1466628223000,
 middleName: null,
 importId: 100000,
 suffix: null,
 lastName: 'Bar',
 licenseNumbers: '[]',
 tags: '["faculty"]',
 degrees: '["MS"]',
 importedEmployeeId: 000000,
 priority: 'master',
 prefix: null,
 importedConstituentId: 000000,
 status: 'active',
 company: true,
 emailAddress: null,
 phoneNumbers:
 [ PhoneNumber {
 ___class: 'PhoneNumber',
 ownerId: null,
 objectId: '85200D8E-E7FB-384A-FFCD-DDD750CFFD00',
 created: '1466629101000',
 updated: null,
 extension: null,
 phoneableType: 'Contact',
 number: '123-123-1234',
 category: 'office',
 phoneableId: 100000,
 importId: 1,
 primary: true,
 ___jsonclass: 'PhoneNumber',
 __meta: '{"relationRemovalIds":{},"selectedProperties":["extension","created","phoneableId","ownerId","phoneableType","number","importId","___saved","___class","catego
ry","updated","objectId","primary"],"relatedObjects":{}}',
 ___dates___: [ '1466629101000' ] } ],
 firstName: 'Foo',
 title: 'Director',
 companyName: 'Some Company',
 counter: 0,
 __meta: '{"relationRemovalIds":{},"selectedProperties":["lastName","created","prefix","companyName","importedConstituentId","counter","suffix","priority","title","ownerId",
"degrees","phoneNumbers","tags","importedEmployeeId","firstName","emailAddress","importId","licenseNumbers","___class","middleName","company","updated","objectId","status"],"
relatedObjects":{}}' }

I see what’s going… Since there is no native support for “Date” objects in JSON, we add the “dates” property to designate date objects. When you send the Contact back, the server fails to recognize that property as one of our own and treats it as a user-defined property (i.e. it attempts to create a column for it), but arrays of primitive values are not allowed, hence is the error.

A temporary workaround would be to remove the dates property from the object before you save it back to the server.

Something else I need to point out… the Standalone build does not have the JS CodeRunner component. As a result, when you deploy your code to the server, it will have no container to run. I recommend using the cloud version for now (if you can).

Regards,
Mark

Okay, I had assumed these were getting cleaned up prior to save. I take it this is something that will eventually get resolved. As for the standalone version, I’m guess that too is on some roadmap. The cloud hosted version isn’t a great choice since we are utilizing most of this behind firewalls.

Thank you for the help.

Both changes are on the roadmap. The first one (dates_ cleanup) should be done sooner than the other.

Regards,
Mark