cancel
Showing results for 
Search instead for 
Did you mean: 

How to correctly add an aspect to a node?

imphilippesimo
Champ on-the-rise
Champ on-the-rise

Hello,

im using alfresco public java APIs to manage an alfresco repository.

Therefore, in one of my methods, i want to add a custom aspect to a node.

i tried to do as it's mentioned in the NodeRef cookbook

ie:

QName CUSTOM_ASPECT_QNAME = QName.createQName("http://www.alfresco.org/model/content/1.0", 'treated');

       QName PROP_QNAME_MY_PROPERTY = QName.createQName("http://www.alfresco.org/model/content/1.0", 'myProperty');

       Map<QName,Serializable> aspectValues = new HashMap<QName,Serializable>();

       aspectValues.put(PROP_QNAME_MY_PROPERTY, value);

       nodeService.addAspect(nodeRef, CUSTOM_ASPECT_QNAME, aspectValues);

      

Unfortunately, i got this exception:

org.alfresco.service.cmr.dictionary.InvalidAspectException: 09040002 The aspect is invalid: {http://www.alfresco.org/model/content/1.0}treated

    at org.alfresco.repo.node.db.DbNodeServiceImpl.addAspect_aroundBody32(DbNodeServiceImpl.java:798)

Can someone tell me what am i doing wrong?

thanks

1 ACCEPTED ANSWER

I  finally succeed, thanks kayne zhang​, each of your answers have been helpful.

In my last post, i made a mistake, cause i defined the same property for many aspects, which threw and exception.

And finally to make it work, i had to put custom-model-context.xml in ${CLASSPATH}/alfresco/extension/

because in the root spring context file of alfresco (applcation-context.xml), every needed xml files are imported there, even the xml file containing "dictionaryModelBootstrap" and "dictionaryBootstrap" beans.

The final config files:

   custom-model-context.xml

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

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"

    default-autowire="autodetect">

    <!-- Registration of new models -->

    <bean id="custommodel.dictionaryBootstrap" parent="dictionaryModelBootstrap"

        depends-on="dictionaryBootstrap">

        <property name="models">

            <list>

                <value>alfresco/extension/customAlfrescoModel.xml</value>

            </list>

        </property>

    </bean>

</beans>

customAlfrescoModel.xml

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

<!-- Definition of new Model -->

<!-- The important part here is the name -->

<model name="koosserydesk:custommodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">

    <!-- Optional meta-data about the model -->

    <description>Koosserydesk Custom Model</description>

    <author>Koosserydesk Team</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 -->

    <namespaces>

        <namespace uri="koosserydesk.custom.model" prefix="koosserydesk" />

    </namespaces>

    <aspects>

        <!-- Custom aspects -->

        <aspect name="koosserydesk:treated">

            <title>koosserydesk treated document aspect</title>

            <properties>

                <property name="koosserydesk:treatedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:treatedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:treatedAnnotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

        <aspect name="koosserydesk:validated">

            <title>koosserydesk validated document aspect</title>

            <properties>

                <property name="koosserydesk:validatedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:validatedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:validatedAnnotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

        <aspect name="koosserydesk:rejected">

            <title>koosserydesk rejected document aspect</title>

            <properties>

                <property name="koosserydesk:rejectedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:rejectedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:rejectedAnnotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

        <aspect name="koosserydesk:signed">

            <title>koosserydesk signed document aspect</title>

            <properties>

                <property name="koosserydesk:signedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:signedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:signedAnnotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

        <aspect name="koosserydesk:vised">

            <title>koosserydesk vised document aspect</title>

            <properties>

                <property name="koosserydesk:visedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:visedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:visedAnnotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

    </aspects>

</model>                       

So in applcation-context.xml, we have somewhere :

...

<import resource="classpath:alfresco/application-context-core.xml" /> ==> this will import "dictionaryModelBootstrap" and "dictionaryBootstrap" beans.

...

<import resource="classpath*:alfresco/extension/*-context.xml"/> ==> which will import our  custom-model-context.xml

In the java code:

  1. QName CUSTOM_ASPECT_QNAME = QName.createQName("koosserydesk.custom.model", 'treated'); 
  2.        QName PROP_QNAME_MY_PROPERTY = QName.createQName("http://www.alfresco.org/model/content/1.0", 'treatedBy'); 
  3.        Map<QName,Serializable> aspectValues = new HashMap<QName,Serializable>(); 
  4.        aspectValues.put(PROP_QNAME_MY_PROPERTY, "imphilippesimo"); 
  5.        nodeService.addAspect(nodeRef, CUSTOM_ASPECT_QNAME, aspectValues); 

View answer in original post

7 REPLIES 7

kaynezhang
World-Class Innovator
World-Class Innovator

The error means your aspect is not defined propertly or is not registered correctly.

Please check your model definition xml file,make sure it is legal and is registered correctly and you are referencing the correct aspect name in your code.

Thanks kayne zhang​ , the namespace i used is the content model namespace proposed by alfresco, it's this one NamespaceService.CONTENT_MODEL_1_0_URI, when i query the database for local names associated to it, i see no 'treated' as this line tries to indicate:

QName CUSTOM_ASPECT_QNAME = QName.createQName("http://www.alfresco.org/model/content/1.0", 'treated');

So i guess that i have to register a new model with a personalized uri and local name. Isn't it?

But can i have a link to show me quickly how to do it?

In order to use customized type/aspect ,you need to define a content model and deploy it into dictionary.

A Content Model is a collection of related Content Types and Aspects which is described in an XML file.

About data dictionary you can refer to https://community.alfresco.com/docs/DOC-4735-data-dictionary-guide

About how to define model and deploy model ,please refer to https://community.alfresco.com/docs/DOC-4735-data-dictionary-guide#w_stepbystepmodeldefinition

thanks kayne zhang​ for the links, i get a better understanding of aspects now.

However, my problem is not yet resolved.

As explained in thos links, in my custom-model-context.xml spring file for bootstraping the model i set this:

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

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"

    default-autowire="autodetect">

    <!-- Registration of new models -->

    <bean id="custommodel.dictionaryBootstrap" parent="dictionaryModelBootstrap"

        depends-on="dictionaryBootstrap">

        <property name="models">

            <list>

                <value>customAlfrescoModel.xml</value>

            </list>

        </property>

    </bean>

</beans>

And in my customAlfrescoModel.xml i have the following:

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

<!-- Definition of new Model -->

<!-- The important part here is the name -->

<model name="koosserydesk:custommodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">

    <!-- Optional meta-data about the model -->

    <description>Koosserydesk Custom Model</description>

    <author>Koosserydesk Team</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 -->

    <namespaces>

        <namespace uri="koosserydesk.custom.model" prefix="koosserydesk" />

    </namespaces> 

    <aspects>

        <!-- Custom aspects -->

        <aspect name="koosserydesk:treated">

            <title>koosserydesk treated document aspect</title>

            <properties>

                <property name="koosserydesk:affixedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:affixedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:annotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

        <aspect name="koosserydesk:validated">

            <title>koosserydesk validated document aspect</title>

            <properties>

                <property name="koosserydesk:affixedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:affixedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:annotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

        <aspect name="koosserydesk:rejected">

            <title>koosserydesk rejected document aspect</title>

            <properties>

                <property name="koosserydesk:affixedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:affixedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:annotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

        <aspect name="koosserydesk:signed">

            <title>koosserydesk signed document aspect</title>

            <properties>

                <property name="koosserydesk:affixedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:affixedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:annotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

        <aspect name="koosserydesk:vised">

            <title>koosserydesk vised document aspect</title>

            <properties>

                <property name="koosserydesk:affixedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:affixedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:annotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

    </aspects>

</model>                       

But when i start the app, spring complains saying it does not find "dictionaryModelBootstrap" and "dictionaryBootstrap" beans.

Invalid bean definition with name 'custommodel.dictionaryBootstrap' defined in class path resource [custom-model-context.xml]: Could not resolve parent bean definition 'dictionaryModelBootstrap'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'dictionaryModelBootstrap' is defined

Where did you place these files?

In your situation you should place custom-model-context.xml into ${ALFRESCO_HOME}\tomcat\shared\classes\alfresco\extension and place  customAlfrescoModel.xml into ${ALFRESCO_HOME}\tomcat\shared\classes .

And make sure  ${ALFRESCO_HOME}\tomcat\shared\classes is configure in your shared classloader.

I  finally succeed, thanks kayne zhang​, each of your answers have been helpful.

In my last post, i made a mistake, cause i defined the same property for many aspects, which threw and exception.

And finally to make it work, i had to put custom-model-context.xml in ${CLASSPATH}/alfresco/extension/

because in the root spring context file of alfresco (applcation-context.xml), every needed xml files are imported there, even the xml file containing "dictionaryModelBootstrap" and "dictionaryBootstrap" beans.

The final config files:

   custom-model-context.xml

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

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"

    default-autowire="autodetect">

    <!-- Registration of new models -->

    <bean id="custommodel.dictionaryBootstrap" parent="dictionaryModelBootstrap"

        depends-on="dictionaryBootstrap">

        <property name="models">

            <list>

                <value>alfresco/extension/customAlfrescoModel.xml</value>

            </list>

        </property>

    </bean>

</beans>

customAlfrescoModel.xml

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

<!-- Definition of new Model -->

<!-- The important part here is the name -->

<model name="koosserydesk:custommodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">

    <!-- Optional meta-data about the model -->

    <description>Koosserydesk Custom Model</description>

    <author>Koosserydesk Team</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 -->

    <namespaces>

        <namespace uri="koosserydesk.custom.model" prefix="koosserydesk" />

    </namespaces>

    <aspects>

        <!-- Custom aspects -->

        <aspect name="koosserydesk:treated">

            <title>koosserydesk treated document aspect</title>

            <properties>

                <property name="koosserydesk:treatedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:treatedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:treatedAnnotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

        <aspect name="koosserydesk:validated">

            <title>koosserydesk validated document aspect</title>

            <properties>

                <property name="koosserydesk:validatedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:validatedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:validatedAnnotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

        <aspect name="koosserydesk:rejected">

            <title>koosserydesk rejected document aspect</title>

            <properties>

                <property name="koosserydesk:rejectedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:rejectedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:rejectedAnnotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

        <aspect name="koosserydesk:signed">

            <title>koosserydesk signed document aspect</title>

            <properties>

                <property name="koosserydesk:signedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:signedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:signedAnnotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

        <aspect name="koosserydesk:vised">

            <title>koosserydesk vised document aspect</title>

            <properties>

                <property name="koosserydesk:visedBy">

                    <type>d:text</type>

                </property>

                <property name="koosserydesk:visedDate">

                    <type>d:datetime</type>

                </property>

                <property name="koosserydesk:visedAnnotation">

                    <type>d:text</type>

                </property>

            </properties>

        </aspect>

    </aspects>

</model>                       

So in applcation-context.xml, we have somewhere :

...

<import resource="classpath:alfresco/application-context-core.xml" /> ==> this will import "dictionaryModelBootstrap" and "dictionaryBootstrap" beans.

...

<import resource="classpath*:alfresco/extension/*-context.xml"/> ==> which will import our  custom-model-context.xml

In the java code:

  1. QName CUSTOM_ASPECT_QNAME = QName.createQName("koosserydesk.custom.model", 'treated'); 
  2.        QName PROP_QNAME_MY_PROPERTY = QName.createQName("http://www.alfresco.org/model/content/1.0", 'treatedBy'); 
  3.        Map<QName,Serializable> aspectValues = new HashMap<QName,Serializable>(); 
  4.        aspectValues.put(PROP_QNAME_MY_PROPERTY, "imphilippesimo"); 
  5.        nodeService.addAspect(nodeRef, CUSTOM_ASPECT_QNAME, aspectValues); 

Congratulations!!!Smiley HappySmiley Happy