cancel
Showing results for 
Search instead for 
Did you mean: 

Using cmis, adding a new secondary type (aspect) removes association aspects, is this a bug?

ianw
Champ in-the-making
Champ in-the-making

The following groovy demonstrates the problem I'm having:

import org.apache.chemistry.opencmis.commons.*

import org.apache.chemistry.opencmis.commons.data.*

import org.apache.chemistry.opencmis.commons.enums.*

import org.apache.chemistry.opencmis.client.api.*

def cmis = new scripts.CMIS(session)

Folder folder  = cmis.getFolder("/Shared")

final String textFileName = "test.txt"

Document doc

try{

    doc = (Document) session.getObjectByPath(folder.getPath()+"/"+textFileName)

}catch(Err){}

if (doc != null){

    doc.delete(true)

}

String mimetype = "text/plain; charset=UTF-8"

String content = "This is some test content"

String filename = textFileName

byte[] buf = content.getBytes("UTF-8")

ByteArrayInputStream input = new ByteArrayInputStream(buf)

ContentStream contentStream = session.getObjectFactory().createContentStream(filename, buf.length, mimetype, input)

Map<String, Object> props = new HashMap<String, Object>()

props.put(PropertyIds.OBJECT_TYPE_ID, "cmis:document")

props.put(PropertyIds.NAME, filename)

doc = folder.createDocument(props, contentStream, VersioningState.MAJOR)

   

List<String> aspects = doc.getPropertyValue("cmis:secondaryObjectTypeIds")

println(aspects)

List<String> toAdd

props.clear()

if (!aspects.contains("R:ncsrel:related")) {

    toAdd = ["P:ncsrel:related"]

    doc = doc.updateProperties(props, toAdd, null)

}

aspects = doc.getPropertyValue("cmis:secondaryObjectTypeIds")

println(aspects)

//problem, adding this aspect removes the R:ncsrel:related

if (!aspects.contains("P:cm:dublincore")) {

    toAdd = ["P:cm:dublincore"]

    doc = doc.updateProperties(props, toAdd, null)

}

aspects = doc.getPropertyValue("cmis:secondaryObjectTypeIds")

println(aspects)

The output is:

[P:cm:titled, P:sys:localized, P:cm:author]

[P:cm:titled, R:ncsrel:related, P:sys:localized, P:cm:author]

[P:cm:titled, P:cm:dublincore, P:sys:localized, P:cm:author]

Adding P:cm:dublincore deleted R:ncsrel:related.

The R:ncsrel:related aspect definition:

    <aspects>
            <aspect name="ncsrel:related">
            <title>NCS Related</title>
            <associations>
                <association name="ncsrel:related">
                    <title>Related Content</title>
                    <source>
                        <mandatory>false</mandatory>
                        <many>true</many>
                    </source>
                    <target>
                        <class>cm:content</class>
                        <mandatory>false</mandatory>
                        <many>true</many>
                    </target>
                </association>
            </associations>
        </aspect>
    </aspects>

c

cts>

Has anyone any thoughts?

1 ACCEPTED ANSWER

afaust
Legendary Innovator
Legendary Innovator

In fact the "aspectsToAdd" is a detail of the CMIS client library and is not transmitted to Alfresco that way. The CMIS specification only provides an updateProperties operation where ALL secondaryTypes / aspects need to be included that should still be applied after the operation (current + new). In case the client library does not correctly merge the existing and aspects to add, Alfresco may remove those aspects that are not in the cmis:secondaryObjectTypeIds list. This is implemented in the CMISConnector.processSecondaryTypes operation.

I would check the HTTP request the client library sends to Alfresco if it contains all the aspects that were applied before PLUS the aspects you want to add.

View answer in original post

9 REPLIES 9

afaust
Legendary Innovator
Legendary Innovator

This is indeed the established behaviour that Alfresco has had the entire time I have been working with it (~6 years). Alfresco may automatically remove aspects when they define associations and/or properties of which none is currently being used on the node or the last of which has just been removed (e.g. if you delete the value of a property defined by an aspect and it was the last property of that aspect, it may be removed). Alfresco will not remove aspects that do not define any properties / associations at all (which can be used for semantic marking).

There are some variations on this behaviour depending on which API is used - I would assume the CMIS integration is built in a way that triggers this automatic removal.

kaynezhang
World-Class Innovator
World-Class Innovator

It seems alfresco will remove aspects that are already in item'existing aspects list but not in aspectsToAdd list in cmis implementation.

To avoid this problem ,you can get all existing aspects first and append them to the aspectsToAdd list.

afaust
Legendary Innovator
Legendary Innovator

In fact the "aspectsToAdd" is a detail of the CMIS client library and is not transmitted to Alfresco that way. The CMIS specification only provides an updateProperties operation where ALL secondaryTypes / aspects need to be included that should still be applied after the operation (current + new). In case the client library does not correctly merge the existing and aspects to add, Alfresco may remove those aspects that are not in the cmis:secondaryObjectTypeIds list. This is implemented in the CMISConnector.processSecondaryTypes operation.

I would check the HTTP request the client library sends to Alfresco if it contains all the aspects that were applied before PLUS the aspects you want to add.

kaynezhang
World-Class Innovator
World-Class Innovator

What I means is that alfresco server cmis implementation  does not correctly merge the existing and aspects to add

It removes the aspects that are in existing aspects list but not  contained in secondaryTypes in the parameter.

So to avoid the error deleting,in the client we can get all existing aspects first and append it to secondaryTypes List we are going to add.

afaust
Legendary Innovator
Legendary Innovator

As I said, merging existing and aspects to add is the responsiblity of the client library before sending the CMIS request. Alfresco is not allowed to override the request data from the client because that would effectively result in users not being able to remove aspects again...

kaynezhang
World-Class Innovator
World-Class Innovator

I got your point alfresco server should design that way .

ianw
Champ in-the-making
Champ in-the-making

I've checked the HTTP request and the existing aspects are indeed missing. I therefore conclude that there is a bug in the opencims client 1.0.0 for the function

CmisObject updateProperties(Map<String,?> properties,

   List<String> addSecondaryTypeIds,

   List<String> removeSecondaryTypeIds)

It seem sensible to use CmisObject updateProperties(Map<String,?> properties), however, when the aspect list is retrieved using getPropertyValue("cmis:secondaryObjectTypeIds") association type aspects are prefixed with "R:". If this is passed to updateProperties the opencmis library throws the error "Secondary types property contains a type that is not a secondary type: R:ncsrel:related". Changing the R: prefix to P: fixes the error, but feels wrong. Is this another problem with the opencmis client?

afaust
Legendary Innovator
Legendary Innovator

I fear the second part about the R: prefix might be a mapping bug inside of Alfresco. You have named the aspect and the association identically. I assume internally Alfresco is mapping Alfresco QNames to CMIS type IDs. The association ncsrel:related is mapped to the CMIS type ID R:ncsrel:related, overriding any prior mapping for the aspect. When Alfresco needs to map the aspect QName back to the CMIS secondary object type ID it picks up the relationship type ID instead.

ianw
Champ in-the-making
Champ in-the-making

Spot on, I've rename the association and all is working.

Thank you very much