Issue
- When trying to update an object definition from one environment (eg. dev) to the other (eg. uat), the process fails with the following error:
com.liferay.object.exception.ObjectFieldNameException$MustNotBeDuplicate: Duplicate name objectFieldName
at com.liferay.object.service.impl.ObjectFieldLocalServiceImpl._validateName(ObjectFieldLocalServiceImpl.java:1407) ~[?:?]
at com.liferay.object.service.impl.ObjectFieldLocalServiceImpl._addObjectField(ObjectFieldLocalServiceImpl.java:813) ~[?:?]
at com.liferay.object.service.impl.ObjectFieldLocalServiceImpl.addCustomObjectField(ObjectFieldLocalServiceImpl.java:136) ~[?:?]
Environment
- Liferay DXP 7.4
Resolution
- Make sure the fields which have the same name in the source and target environment also have the same externalReferenceCode.
- As of DXP 7.4 2024.Q1, the externalReferenceCode of an object field cannot be consulted or updated from the Object Definition GUI. You have to use the ObjectDefinition API.
APIs to use:
- Use this API in both environments to get the objectFieldId's for each fields of an Object Definition using its objectDefinitionId (xxxxx):
GET /o/object-admin/v1.0/object-definitions/xxxxx
- Use this API in both environments to read the externalReferenceCode of an Object Field given its objectFieldId (yyyyy):
GET /o/object-admin/v1.0/object-fields/yyyyy
- And eventually, use this API in the source environment to patch the externalReferenceCode of an Object Field given its objectFieldId (yyyyy) so that it matches the targets:
PATCH /o/object-admin/v1.0/object-fields/yyyyy
with the following body:
{
"externalReferenceCode": "70c0d71c-ba78-f4df-61b8-4db5e4ba8aeb"
}
As soon as object fields with the same name have matching external reference codes in both environments, you can try again.
Additional Information
- When an object definition is updated, Liferay goes through the list of object fields and for each of them decides whether the field has to be updated or created.
- Liferay first tries to match the field by its objectFieldId which is likely to be different from one environment to the other.
- Then, it tries to match the field by its externalReferenceCode.
- If no field is matching, Liferay assumes that the field has to be created but its creation will violate the field name unicity rule.
- This logic can be seen in this method: https://github.com/liferay/liferay-portal/blob/master/modules/apps/object/object-service/src/main/java/com/liferay/object/service/impl/ObjectFieldLocalServiceImpl.java#L153
Most of the time, this issue is not supposed to happen. However, here is a typical scenario where the issue will happen:
- An object definition is created in dev, exported and imported in uat. At this point, all fields have the same externalReferenceCode in both environments.
- A new field is added manually in both environments, they will have a different random externalReferenceCode.
- The next time you are going to import the object definition from dev to uat, the update will fail because of the manually added field unless you update it using the API so that they share the same externalReferenceCode.