Backendless Support
 
Solved

Backendless 4. Unable to create relation.

Error : Unable to create relation. Child object with id 'null' is not found in the related table.

  1. Backendless.UserService.register(user, new AsyncCallback<BackendlessUser>() {

    public void handleResponse(BackendlessUser registeredUser) {

    ArrayList<Gender> children = new ArrayList<>();

    children.add( choosenGender );

    Log.e("app", "id "+choosenGender.getObjectId());// return value

    Backendless.Data.of(BackendlessUser.class).setRelation(registeredUser, "gender", children, new AsyncCallback<Void>() {

    @Override

    public void handleResponse(Void response) {

    Log.e("app", response.toString());

    }

    @Override

    public void handleFault(BackendlessFault fault) {

    Log.e("app", "Error " + fault.getMessage()); // here i get the error

    }

    });

    }

    public void handleFault(BackendlessFault fault) {

    Toast.makeText(SignupActivity.this, "Error " + fault.getMessage(), Toast.LENGTH_SHORT).show();

    }

    });

class Gender i have generated using Backendless codegen + added public constructor

Gender.class

  1. import android.os.Parcel;

    import android.os.Parcelable;

    import com.backendless.Backendless;

    import com.backendless.async.callback.AsyncCallback;

    public class Gender implements Parcelable {

    private String objectId;

    private Integer id;

    private String title;

    private java.util.Date updated;

    private String ownerId;

    private java.util.Date created;

    public Gender() {

    }

    protected Gender(Parcel in) {

    objectId = in.readString();

    title = in.readString();

    ownerId = in.readString();

    }

    public static final Creator<Gender> CREATOR = new Creator<Gender>() {

    @Override

    public Gender createFromParcel(Parcel in) {

    return new Gender(in);

    }

    @Override

    public Gender[] newArray(int size) {

    return new Gender[size];

    }

    };

    public String getObjectId() {

    return objectId;

    }

    public Integer getId() {

    return id;

    }

    public void setId(Integer id) {

    this.id = id;

    }

    public String getTitle() {

    return title;

    }

    public void setTitle(String title) {

    this.title = title;

    }

    public java.util.Date getUpdated() {

    return updated;

    }

    public String getOwnerId() {

    return ownerId;

    }

    public java.util.Date getCreated() {

    return created;

    }

    public Gender save() {

    return Backendless.Data.of(Gender.class).save(this);

    }

    public void saveAsync(AsyncCallback<Gender> callback) {

    Backendless.Data.of(Gender.class).save(this, callback);

    }

    public Long remove() {

    return Backendless.Data.of(Gender.class).remove(this);

    }

    public void removeAsync(AsyncCallback<Long> callback) {

    Backendless.Data.of(Gender.class).remove(this, callback);

    }

    public static Gender findById(String id) {

    return Backendless.Data.of(Gender.class).findById(id);

    }

    public static void findByIdAsync(String id, AsyncCallback<Gender> callback) {

    Backendless.Data.of(Gender.class).findById(id, callback);

    }

    public static Gender findFirst() {

    return Backendless.Data.of(Gender.class).findFirst();

    }

    public static void findFirstAsync(AsyncCallback<Gender> callback) {

    Backendless.Data.of(Gender.class).findFirst(callback);

    }

    public static Gender findLast() {

    return Backendless.Data.of(Gender.class).findLast();

    }

    public static void findLastAsync(AsyncCallback<Gender> callback) {

    Backendless.Data.of(Gender.class).findLast(callback);

    }

    @Override

    public int describeContents() {

    return 0;

    }

    @Override

    public void writeToParcel(Parcel parcel, int i) {

    parcel.writeString(objectId);

    parcel.writeString(title);

    parcel.writeString(ownerId);

    }

    }

Leave a Comment

Comments (18)

photo
1

Hi Valeria,

Having just the "get" methods is not sufficient to declare a property in Backendless, you need to add setters as well. Because of that the Gender object you add the relation for will not have the assigned objectId.

Regards,

Mark

photo
1

have added all setters, but the same error

this is how i get values from backendless table:

  1. Backendless.Data.of(Gender.class).find(new AsyncCallback<List<Gender>>() {
  2. @Override
  3. public void handleResponse(List<Gender> response) {
  4. if (response != null) {
  5. genderList.addAll(response);
  6. }
  7. }
  8. @Override
  9. public void handleFault(BackendlessFault fault) {
  10. Log.e("app", fault.getMessage());
  11. }
  12. });

photo
1

Could you please check (either in debugger or with logging) that the Gender objects received in that call have assigned objectId values?

photo
1

All objectId are ok

  1. E/app: Received data
  2. E/app: Gender{objectId='55060E31-752B-8A6E-FF17-15FADD0DF800', id=1, title='male', updated=null, ownerId='null', created=Mon Apr 10 19:20:37 GMT+03:00 2017}
  3. E/app: Gender{objectId='FD5A1376-DDD6-3324-FF15-9D23B1ED3400', id=2, title='female', updated=null, ownerId='null', created=Mon Apr 10 19:20:45 GMT+03:00 2017}

  1. Before setRelation
  2. E/app: Gender{objectId='55060E31-752B-8A6E-FF17-15FADD0DF800', id=1, title='male', updated=null, ownerId='null', created=Mon Apr 10 19:20:37 GMT+03:00 2017}
  3. E/app: Gender{objectId='FD5A1376-DDD6-3324-FF15-9D23B1ED3400', id=2, title='female', updated=null, ownerId='null', created=Mon Apr 10 19:20:45 GMT+03:00 2017}
  4. E/app: Array list 'children'
  5. E/app: Gender{objectId='FD5A1376-DDD6-3324-FF15-9D23B1ED3400', id=2, title='female', updated=null, ownerId='null', created=Mon Apr 10 19:20:45 GMT+03:00 2017}

photo
1

Thanks. Could you please re-post the Gender class and also let me know your application ID?

photo
1

Gender.class

  1. public class Gender implements Parcelable {

    private String objectId;

    private Integer id;

    private String title;

    private java.util.Date updated;

    private String ownerId;

    private java.util.Date created;

    public Gender() {

    }

    @Override

    public String toString() {

    return "Gender{" +

    "objectId='" + objectId + '\'' +

    ", id=" + id +

    ", title='" + title + '\'' +

    ", updated=" + updated +

    ", ownerId='" + ownerId + '\'' +

    ", created=" + created +

    '}';

    }

    protected Gender(Parcel in) {

    objectId = in.readString();

    title = in.readString();

    ownerId = in.readString();

    }

    public void setObjectId(String objectId) {

    this.objectId = objectId;

    }

    public void setUpdated(Date updated) {

    this.updated = updated;

    }

    public void setOwnerId(String ownerId) {

    this.ownerId = ownerId;

    }

    public void setCreated(Date created) {

    this.created = created;

    }

    public static Creator<Gender> getCREATOR() {

    return CREATOR;

    }

    public static final Creator<Gender> CREATOR = new Creator<Gender>() {

    @Override

    public Gender createFromParcel(Parcel in) {

    return new Gender(in);

    }

    @Override

    public Gender[] newArray(int size) {

    return new Gender[size];

    }

    };

    public String getObjectId() {

    return objectId;

    }

    public Integer getId() {

    return id;

    }

    public void setId(Integer id) {

    this.id = id;

    }

    public String getTitle() {

    return title;

    }

    public void setTitle(String title) {

    this.title = title;

    }

    public java.util.Date getUpdated() {

    return updated;

    }

    public String getOwnerId() {

    return ownerId;

    }

    public java.util.Date getCreated() {

    return created;

    }

    public Gender save() {

    return Backendless.Data.of(Gender.class).save(this);

    }

    public void saveAsync(AsyncCallback<Gender> callback) {

    Backendless.Data.of(Gender.class).save(this, callback);

    }

    public Long remove() {

    return Backendless.Data.of(Gender.class).remove(this);

    }

    public void removeAsync(AsyncCallback<Long> callback) {

    Backendless.Data.of(Gender.class).remove(this, callback);

    }

    public static Gender findById(String id) {

    return Backendless.Data.of(Gender.class).findById(id);

    }

    public static void findByIdAsync(String id, AsyncCallback<Gender> callback) {

    Backendless.Data.of(Gender.class).findById(id, callback);

    }

    public static Gender findFirst() {

    return Backendless.Data.of(Gender.class).findFirst();

    }

    public static void findFirstAsync(AsyncCallback<Gender> callback) {

    Backendless.Data.of(Gender.class).findFirst(callback);

    }

    public static Gender findLast() {

    return Backendless.Data.of(Gender.class).findLast();

    }

    public static void findLastAsync(AsyncCallback<Gender> callback) {

    Backendless.Data.of(Gender.class).findLast(callback);

    }

    @Override

    public int describeContents() {

    return 0;

    }

    @Override

    public void writeToParcel(Parcel parcel, int i) {

    parcel.writeString(objectId);

    parcel.writeString(title);

    parcel.writeString(ownerId);

    }

    }

Application ID

98E4525D-1575-0ECD-FF3A-E8046DE72A00

photo
1

Thanks. I was able to reproduce the problem and am working on a resolution.

Regards,

Mark

photo
2

Okay, got this resolved. Could you please grab a build of backendless.jar from the following link and replace the library reference in your project:

https://github.com/Backendless/Android-SDK/tree/4_0/out

Then re-run and let me know if it works.

Regards,

Mark

photo
1

Yes, Mark! Now it works :)

Thank you!

Regards,

Valeria

photo
photo
1

I have same issue on JS Custom logic:

  1. //Save Request

    return requestsStorage.save(requestObject).then(function (savedObject) {

    console.log(savedObject);

    //Add relations

    return requestsStorage.setRelation(savedObject,"from",[currentUser]).then(function (count) {

    console.log(count);

    //Update object and return

    savedObject.from = currentUser;

    return requestsStorage.setRelation(savedObject,"to",[requestedUser]).then(function (count) {

    console.log(count);

    savedObject.to = requestedUser;

    return savedObject;

    }).catch(function (relationErr) {

    console.error(relationErr);

    return relationErr;

    })

    }).catch(function (relationErr) {

    console.error(relationErr);

    return relationErr;

    })

    }).catch(function (savingErr) {

    console.error(savingErr);

    return savingErr;

    });

In my case, first set of relation works, but second failed with error:

{

"code": 1303,

"message": "Unable to create relation. Child object with id 'null' is not found in the related table."

}

Obviously objects contain objectId, this I've checked

photo
1

Which one of these calls fails?

photo
1

As i said, second set relation =>

return requestsStorage.setRelation(savedObject,"to",[requestedUser]).then(function (count) {

console.log(count);

savedObject.to = requestedUser;

return savedObject;

}).catch(function (relationErr) {

console.error(relationErr);

return relationErr;

})

photo
1

could you add "console.log( rquestedUser )" before the call and let us know what it prints?

Also, does the "to" column exist in the table where "savedObject" is stored?

photo
1

Yes column is created.

  1. [ User {
  2. lastLogin: 1495043860000,
  3. userStatus: 'ENABLED',
  4. created: 1495043687514,
  5. avatar: null,
  6. ownerId: '626EC44A-5DAA-3B34-FFB0-A733BB011A00',
  7. __meta: '{"relationRemovalIds":{},"selectedProperties":["password","created","name","___class","online","avatar","ownerId","updated","objectId","email","status"],"relatedObjects":{}}',
  8. name: 'Tomas Radvansky',
  9. ___class: 'Users',
  10. online: null,
  11. updated: 1495045416172,
  12. objectId: '626EC44A-5DAA-3B34-FFB0-A733BB011A00',
  13. email: 'radvansky.tomas@gmail.com',
  14. status: null } ]
  15. { code: 1303,
  16. message: 'Unable to create relation. Child object with id \'null\' is not found in the related table.' }

photo
1

Hi Tomas,

I have tried to reproduce your problem but could not.

I've created a small script to play your scenario. Please, look on it and let us know if is it proper for your case.

If not, please provide us something similar. I mean some small code sample for reproducing your issue.

Regards Ilya

photo
1

Full source code of endpoint:

  1. /**

    * @param {String} userEmail

    * @returns {Promise.<void>}

    */

    sendContactRequest(userEmail) {

    let TAG = 'EventsService.sendContactRequest - ';

    //Get Current User Object

    let usersStorage = Backendless.Persistence.of(Backendless.User);

    let currentUser = { objectId:this.request.context.userId };

    //Get Requested User

    console.log(currentUser);

    let queryBuilder = Backendless.DataQueryBuilder.create();

    queryBuilder.setWhereClause("email = '" + userEmail + "'");

    return usersStorage.find(queryBuilder).then(function (requestedUser) {

    console.log(requestedUser);

    let requestsStorage = Backendless.Persistence.of(Requests);

    let requestObject = new Requests();

    requestObject.status = 0;

    //Save Request

    return requestsStorage.save(requestObject).then(function (savedObject) {

    console.log(savedObject);

    //Add relations

    return requestsStorage.setRelation(savedObject,"from",[currentUser]).then(function (count) {

    console.log(requestedUser);

    //Update object and return

    savedObject.from = currentUser;

    return requestsStorage.setRelation(savedObject,"to",[requestedUser]).then(function (count) {

    console.log(count);

    savedObject.to = requestedUser;

    return savedObject;

    }).catch(function (relationErr) {

    console.error(relationErr);

    return relationErr;

    })

    }).catch(function (relationErr) {

    console.error(relationErr);

    return relationErr;

    })

    }).catch(function (savingErr) {

    console.error(savingErr);

    return savingErr;

    });

    }).catch(function (requestedErr) {

    console.error(requestedErr);

    return requestedErr;

    });

    //Post notification

    }

You can access service directly:

curl -X "POST" "https://api.backendless.com/02E0B487-71CE-DB1E-FF7F-79892D128500/E4A4091B-3ED0-9AD1-FFB0-A08606BEDC00/services/EventsService/1.0.0/sendContactRequest"; \

-H 'Content-Type: application/json' \

-H 'Accept: application/json' \

-H 'user-token: BE416AFD-B633-180D-FFA6-ED3619EC8900' \

-d $'"radvansky.tomas@gmail.com"'

Reply:

{

"code": 1303,

"message": "Unable to create relation. Child object with id 'null' is not found in the related table."

}

photo
1

Thank, Tomas.

Seems I found the problem. The result of calling usersStorage.find is an array. It means you don't have to wrap it in [] before passing it to setRelation method.

Please, try to use this code for creating the second relation ('to')

  1. ...
  2. return requestsStorage.setRelation(savedObject,"to", requestedUser)
  3. ...

photo
1

Big F-Word

Sorry about that...sorted

photo