guys at Alfresco,
I found a work around but I am not sure if it is orthodox ! It is a simple hack and an explanation how to prevent the above error to happen. The Java class concerned is :
projects/repository/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java
method : setNodePropertiesImpl
The problem is that at line 1701 in the original class where the exception is raised we have this :
ContentDataWithId contentDataWithId = (ContentDataWithId) valueToDelete.getValue(DataTypeDefinition.CONTENT);
here, there is a casting done on a serialized object which "sometimes" is NOT ContentDataWithId. In general it is common practice in Java to perform a test on a serialized object's type before using it in order to make sure there is no error at run-time. So I have changed the code as below in red, the error does not occur anymore. However I am not sure about possible side effects.
- What to do with objects which are not of type ContentDataWithId ?
- Are there other coding errors like these across the sources, if yes we are all running on a mine field on the community edition…
Quick fix coded in red :
// Add or remove properties as we go
ContentDataWithId cdwi;
for (Map.Entry<NodePropertyKey, MapValueComparison> entry : persistableDiff.entrySet())
{
NodePropertyKey key = entry.getKey();
QName qname = qnameDAO.getQName(key.getQnameId()).getSecond();
PropertyDefinition removePropDef = dictionaryService.getProperty(qname);
boolean isContent = (removePropDef != null &&
removePropDef.getDataType().getName().equals(DataTypeDefinition.CONTENT));
switch (entry.getValue())
{
case NULL:
case EQUAL:
// The entries are the same
propsToDelete.remove(key);
propsToAdd.remove(key);
continue;
case RIGHT_ONLY:
// Only in new props: add
propsToDelete.remove(key);
// Handle new content
if (isContent)
{
// The new value needs conversion to the ID-based ContentData reference
NodePropertyValue newPropValue = propsToAdd.get(key);
ContentData newContentData = (ContentData) newPropValue.getValue(DataTypeDefinition.CONTENT);
if (newContentData != null)
{
Long newContentDataId = contentDataDAO.createContentData(newContentData).getFirst();
cdwi = new ContentDataWithId(newContentData, newContentDataId);
newPropValue = new NodePropertyValue(DataTypeDefinition.CONTENT, new ContentDataId(newContentDataId));
propsToAdd.put(key, newPropValue);
newPropsRaw.put(key, new NodePropertyValue(DataTypeDefinition.CONTENT, cdwi));
}
}
continue;
case LEFT_ONLY:
// Only present in old props: must not be added
propsToAdd.remove(key);
// Handle deleted content
if (isContent)
{
// The old values will be an ID-based ContentData reference
NodePropertyValue valueToDelete = propsToDelete.get(key);
if (valueToDelete.getValue(DataTypeDefinition.CONTENT) instanceof ContentDataWithId) {
cdwi = (ContentDataWithId) valueToDelete.getValue(DataTypeDefinition.CONTENT);
if (cdwi != null) {
Long contentDataId = cdwi.getId();
contentDataDAO.deleteContentData(contentDataId);
}
} else {
// What needs to be done here, when the object is not the type expected ?
}
}
continue;
case NOT_EQUAL:
// Value has changed: remove and add
if (isContent)
{
// The old values will be an ID-based ContentData reference
NodePropertyValue valueToDelete = propsToDelete.get(key);
if (valueToDelete.getValue(DataTypeDefinition.CONTENT) instanceof ContentDataWithId) {
cdwi = (ContentDataWithId) valueToDelete.getValue(DataTypeDefinition.CONTENT);
if (cdwi != null) {
Long contentDataId = cdwi.getId();
contentDataDAO.deleteContentData(contentDataId);
}
} else {
// What needs to be done here, when the object is not the type expected ?
}
// The new value needs conversion to the ID-based ContentData reference
NodePropertyValue newPropValue = propsToAdd.get(key);
ContentData newContentData = (ContentData) newPropValue.getValue(DataTypeDefinition.CONTENT);
if (newContentData != null)
{
Long newContentDataId = contentDataDAO.createContentData(newContentData).getFirst();
cdwi = new ContentDataWithId(newContentData, newContentDataId);
newPropValue = new NodePropertyValue(DataTypeDefinition.CONTENT, new ContentDataId(newContentDataId));
propsToAdd.put(key, newPropValue);
newPropsRaw.put(key, new NodePropertyValue(DataTypeDefinition.CONTENT, cdwi));
}
}
continue;
default:
throw new IllegalStateException("Unknown MapValueComparison: " + entry.getValue());
}
}