Business Logic afterUpdate InvalidEntityException

I’m working on an Android app that saves objects to Backendless using the following method in a background thread.

response = Backendless.Data.of(ListItem.class).save(mListItem);

Without Business Logic in place this method works. My object is updated in Backendless.

Now I want to do some logic after the object is saved. I’ve generated code for my business logic and via CodeRunner and I’m able step through my business logic code.

Now the above save method returns the following error in the afterUpdate callback:
Code = 0; exceptionClass = “class com.backendless.exceptions.persistence.InvalidEntityException”; exceptionMessage = “Duplicate property:id”

Back in my Android app I now receive the following BackendlessException: Code: 8001; Message: Duplicate property: id.

My afterUpdate code is shown below. It does nothing, but simply allows me the opportunity to insert a break point.

@Override

public void afterUpdate(RunnerContext context, ListItem listitem, ExecutionResult<ListItem> result) throws Exception {

try {


    int temp=0;


} catch (Exception e) {


    e.printStackTrace();


}

}

Any thoughts on why without Business Logic in place my save method works and with it in place I get an error?

Hi Loren,

Could you please also provide the source code of ListItem class?

Here’s the ListItem class that is used in the Business Logic.

package com.alist.models;

import com.backendless.Backendless;
import com.backendless.BackendlessUser;
import com.backendless.geo.GeoPoint;

import java.util.Date;
import java.util.UUID;

public class ListItem
{
private long Id;
private String uuid;
private String objectId;

private String name;
private String listTitleUuid;
private String deviceUuid;
private String messageChannel;
private long manualSortKey;
private boolean checked;
private boolean favorite;
private boolean markedForDeletion;
private boolean struckOut;

private Date updated;
private Date created;

public ListItem() {
// A default constructor.
}

//region Getters and Setters
public long getId() {
return Id;
}

public void setId(long id) {
Id = id;
}

public String getUuid() {
return uuid;
}

public void setUuid(String uuid) {
this.uuid = uuid;
}

public String getObjectId() {
return objectId;
}

public void setObjectId(String objectId) {
this.objectId = objectId;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getListTitleUuid() {
return listTitleUuid;
}

public void setListTitleUuid(String listTitleUuid) {
this.listTitleUuid = listTitleUuid;
}

public String getDeviceUuid() {
return deviceUuid;
}

public void setDeviceUuid(String deviceUuid) {
this.deviceUuid = deviceUuid;
}

public String getMessageChannel() {
return messageChannel;
}

public void setMessageChannel(String messageChannel) {
this.messageChannel = messageChannel;
}

public long getManualSortKey() {
return manualSortKey;
}

public void setManualSortKey(long manualSortKey) {
this.manualSortKey = manualSortKey;
}

public boolean isChecked() {
return checked;
}

public void setChecked(boolean checked) {
this.checked = checked;
}

public boolean isFavorite() {
return favorite;
}

public void setFavorite(boolean favorite) {
this.favorite = favorite;
}

public boolean isMarkedForDeletion() {
return markedForDeletion;
}

public void setMarkedForDeletion(boolean markedForDeletion) {
this.markedForDeletion = markedForDeletion;
}

public boolean isStruckOut() {
return struckOut;
}

public void setStruckOut(boolean struckOut) {
this.struckOut = struckOut;
}

public Date getUpdated() {
return updated;
}

public void setUpdated(Date updated) {
this.updated = updated;
}

public Date getCreated() {
return created;
}

public void setCreated(Date created) {
this.created = created;
}
//endregion

@Override
public String toString() {
return getName();
}

// public void setObjectId( String objectId )
// {
// this.objectId = objectId;
// }

public ListItem save()
{
return Backendless.Data.of( ListItem.class ).save( this );
}

public Long remove()
{
return Backendless.Data.of( ListItem.class ).remove( this );
}

public static ListItem findById( String id )
{
return Backendless.Data.of( ListItem.class ).findById( id );
}

public static ListItem findFirst()
{
return Backendless.Data.of( ListItem.class ).findFirst();
}

public static ListItem findLast()
{
return Backendless.Data.of( ListItem.class ).findLast();
}
}
And here’s the one being used in my Android app. I believe the only difference is in a couple of the helper methods.package com.lbconsulting.a1list.domain.model;

import com.lbconsulting.a1list.AndroidApplication;
import com.lbconsulting.a1list.domain.repositories.ListTitleRepository;
import com.lbconsulting.a1list.utils.MySettings;

import java.util.Date;
import java.util.UUID;

/**

  • Java object for an A1List ListItem.
    */
    public class ListItem {

    private long Id;
    private String uuid;
    private String objectId;

    private String name;
    private String listTitleUuid;
    private String deviceUuid;
    private String messageChannel;
    private long manualSortKey;
    private boolean checked;
    private boolean favorite;
    private boolean markedForDeletion;
    private boolean struckOut;

    private Date updated;
    private Date created;

    public ListItem() {
    // A default constructor.
    }

    public static ListItem newInstance(String name, ListTitle listTitle, boolean saveNextSortKeyToBackendless) {
    ListTitleRepository listTitleRepository = AndroidApplication.getListTitleRepository();
    ListItem newListItem = new ListItem();

     String newUuid = UUID.randomUUID().toString();
     // replace uuid "-" with "_" to distinguish it from Backendless objectId
     newUuid = newUuid.replace("-", "_");
     newListItem.setUuid(newUuid);
    
     newListItem.setName(name);
     newListItem.setListTitleUuid(listTitle.getUuid());
     newListItem.setDeviceUuid(MySettings.getDeviceUuid());
     newListItem.setMessageChannel(MySettings.getActiveUserID());
     newListItem.setManualSortKey(listTitleRepository.retrieveListItemNextSortKey(listTitle, saveNextSortKeyToBackendless));
     newListItem.setChecked(false);
     newListItem.setFavorite(false);
     newListItem.setMarkedForDeletion(false);
     newListItem.setStruckOut(false);
    
     return newListItem;
    

    }

    //region Getters and Setters
    public long getId() {
    return Id;
    }

    public void setId(long id) {
    Id = id;
    }

    public String getUuid() {
    return uuid;
    }

    public void setUuid(String uuid) {
    this.uuid = uuid;
    }

    public String getObjectId() {
    return objectId;
    }

    public void setObjectId(String objectId) {
    this.objectId = objectId;
    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public ListTitle retrieveListTitle() {
    return AndroidApplication.getListTitleRepository().retrieveListTitleByUuid(listTitleUuid);
    }

    public String getListTitleUuid() {
    return listTitleUuid;
    }

    public void setListTitleUuid(String listTitleUuid) {
    this.listTitleUuid = listTitleUuid;
    }

    public String getDeviceUuid() {
    return deviceUuid;
    }

    public void setDeviceUuid(String deviceUuid) {
    this.deviceUuid = deviceUuid;
    }

    public String getMessageChannel() {
    return messageChannel;
    }

    public void setMessageChannel(String messageChannel) {
    this.messageChannel = messageChannel;
    }

    public long getManualSortKey() {
    return manualSortKey;
    }

    public void setManualSortKey(long manualSortKey) {
    this.manualSortKey = manualSortKey;
    }

    public boolean isChecked() {
    return checked;
    }

    public void setChecked(boolean checked) {
    this.checked = checked;
    }

    public boolean isFavorite() {
    return favorite;
    }

    public void setFavorite(boolean favorite) {
    this.favorite = favorite;
    }

    public boolean isMarkedForDeletion() {
    return markedForDeletion;
    }

    public void setMarkedForDeletion(boolean markedForDeletion) {
    this.markedForDeletion = markedForDeletion;

    }

    public boolean isStruckOut() {
    return struckOut;
    }

    public void setStruckOut(boolean struckOut) {
    this.struckOut = struckOut;
    }

    public Date getUpdated() {
    return updated;
    }

    public void setUpdated(Date updated) {
    this.updated = updated;
    }

    public Date getCreated() {
    return created;
    }

    public void setCreated(Date created) {
    this.created = created;
    }
    //endregion

    @Override
    public String toString() {
    return getName();
    }
    }

Loren,

despite the error you’re getting, could you check if the object is actually saved?

Mark

Mark … when the Business Logic is running the object is not saved. I receive a “BackendlessException: Code: 8001; Message: Duplicate property: id” in my Android app.

When the Business Logic is NOT running, the object is saved with no error.

Could you please check the name of the “id” property in the table on the backend - does it start with a capitalized letter or the lower-case letter?

The Data Management Console shows the"id" field starting with a lower-case letter.

Problem solved.

In my object class I had a long field with the name Id … that’s capital “I” lower case d. But when Backendless created my table it created the field’s name as lower case “id”. So I changed the field’s name in my class from “Id” to “SQLiteId” (along with the applicable getter and setter) and now no error occurs when I run the Business Logic.

So the moral of the story … you apparently can not have a class field name of “Id” or “id”.

Thanks for your help.