Backendless 4. Unable to create relation.

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

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

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);
    }
}


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

have added all setters, but the same error

this is how i get values from backendless table:



Backendless.Data.of(Gender.class).find(new AsyncCallback<List<Gender>>() {
@Override
public void handleResponse(List<Gender> response) {
if (response != null) {
genderList.addAll(response);
}
    }


@Override
public void handleFault(BackendlessFault fault) {
        Log.e("app", fault.getMessage());
}
});

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

All objectId are ok

E/app: Received data
 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}
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}
Before setRelation
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}
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}


E/app: Array list 'children'
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}

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

Gender.class

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

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

Regards,
Mark

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

Yes, Mark! Now it works :slight_smile:

Thank you!

Regards,
Valeria

I have same issue on JS Custom logic:

//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

Which one of these calls fails?

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;
})

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?

Yes column is created.


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

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

Full source code of endpoint:

/**
 * @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.”
}

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’)

...
return requestsStorage.setRelation(savedObject,"to", requestedUser)
...

Big F-Word

Sorry about that…sorted