Search code examples
alfrescocmisopencmis

Alresco CMIS multi aspect with same properties name


Here it is a short description of the situation:

I am declaring a new bean in a private Jar file to add two new Aspects to match Secondary Type feature from CMIS 1.1 specification.

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
    <!-- Registration of new models --> 
    <bean id="myExtension" parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
        <property name="models">
            <list>
                <value>alfresco/extension/my-extension-model_1.xml</value>
                <value>alfresco/extension/my-extension-model_2.xml</value>
            </list>
        </property>
    </bean>
</beans>

Here is the code of my-extension-model_1.xml:

<?xml version="1.0" encoding="UTF-8"?>

<!-- Definition of new Model -->

<!-- The important part here is the name - Note: the use of the my: namespace 
    which is defined further on in the document -->
<model name="my:model_1" xmlns="http://www.alfresco.org/model/dictionary/1.0">

    <!-- Optional meta-data about the model -->
    <description>Model 1</description>
    <author>mtyc</author>
    <version>1.0</version>

    <!-- Imports are required to allow references to definitions in other models -->
    <imports>
        <!-- Import Alfresco Dictionary Definitions -->
        <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d" />
        <!-- Import Alfresco Content Domain Model Definitions -->
        <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm" />
    </imports>

    <!-- Introduction of new namespaces defined by this model -->
    <!-- NOTE: The following namespace my.new.model should be changed to reflect 
        your own namespace -->
    <namespaces>
        <namespace uri="http://www.mycompany.com/model/content/1.0" prefix="my" />
    </namespaces>

    <aspects>
        <aspect name="my:model_1_DedicatedAspect">
            <title>My model 1 aspect</title>
            <properties>
                <property name="my:supplierId">
                    <type>d:text</type>
                    <mandatory>true</mandatory>
                </property>
                <property name="my:companyId">
                    <type>d:text</type>
                    <mandatory>true</mandatory>
                </property>
                <property name="my:orderId">
                     <type>d:text</type>
                </property>
            </properties>
        </aspect>
    </aspects>
</model>

Here is the code of my-extension-model_2.xml:

<?xml version="1.0" encoding="UTF-8"?>

<!-- Definition of new Model -->

<!-- The important part here is the name - Note: the use of the my: namespace 
    which is defined further on in the document -->
<model name="my:model_2" xmlns="http://www.alfresco.org/model/dictionary/1.0">

    <!-- Optional meta-data about the model -->
    <description>Model 2</description>
    <author>mtyc</author>
    <version>1.0</version>

    <!-- Imports are required to allow references to definitions in other models -->
    <imports>
        <!-- Import Alfresco Dictionary Definitions -->
        <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d" />
        <!-- Import Alfresco Content Domain Model Definitions -->
        <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm" />
    </imports>

    <!-- Introduction of new namespaces defined by this model -->
    <!-- NOTE: The following namespace my.new.model should be changed to reflect 
        your own namespace -->
    <namespaces>
        <namespace uri="http://www.mycompany.com/model/content/1.0" prefix="my" />
    </namespaces>

    <aspects>
        <aspect name="my:model_2_DedicatedAspect">
            <title>My model 2 aspect</title>
            <properties>
                <property name="my:supplierId">
                    <type>d:text</type>
                    <mandatory>true</mandatory>
                </property>
                <property name="my:companyId">
                    <type>d:text</type>
                    <mandatory>true</mandatory>
                </property>
            </properties>
        </aspect>
    </aspects>
</model>    

I then build it as a jar and deploy it under Alfresco, which starts successfully and load my models.

In the application I am developing, which is communicating with my alfresco instance, I create documents with aspect my:model_1_DedicatedAspect and documents with aspect my:model_2_DedicatedAspect.

I want to search documents by my:companyId belonging to aspect my:model_1_DedicatedAspect using this CMIS query:

private static ItemIterable<QueryResult> searchClaimsByCompanyId(Session session, String companyId) {
    String query = "SELECT d.*, t.* FROM cmis:document as d JOIN my:model_1_DedicatedAspect as t ON d.cmis:objectId = t.cmis:objectId where t.my:companyId = '" + companyId + "'";
    ItemIterable<QueryResult> result = session.query(query, false);
    return result;
}

The problem is: Result contains documents created with aspect my:model_1_DedicatedAspect BUT ALSO documents created with aspect my:model_2_DedicatedAspect.

After deeper tests, I observed that when I create a document using my:model_1_DedicatedAspect, document is also associated with aspect my:model_2_DedicatedAspect.

Questions: Is there something I am doing wrong ? Is this a bug ? Is there a better way ?

Thanks a lot for your answers, Max


Solution

  • I'm not sure why it's not giving an error on start-up. But in Alfresco a property must be unique in it's model. So your my:companyId is used twice in different aspects.

    The best practice is to create 1 aspect called my:company which has a property my:companyId.

    You can just define aspects without property to have a check or search on them.

    And btw the CMIS query can be made much easier: SELECT * FROM my:model_1_DedicatedAspect

    So no need for extra joins.

    ----------UPDATE----------

    Since a certain version of Alfresco (I guess it's 4.x) you don't need to add a certain aspect to a node anymore. If you add the aspects property in your case my:companyId, then it will determine which aspect to add automatically. So Alfresco sees 2 aspects with the same property and adds them.

    I still haven't heard from you "Why" you're doing it like this? In sense of Content Modeling this doesn't make any sense. Aspects are just Alfresco's way to add dynamically properties to different content Types.

    In your case I'd use inheritance to include the needed property.