cancel
Showing results for 
Search instead for 
Did you mean: 

Automatically manage a property of a custom aspect

joeforte
Champ in-the-making
Champ in-the-making
Hi, I'm a beginner about Alfresco and I have a question.
I created a model with the following custom aspect (the configuration of the property is not the definitive one):

<aspect name="gs:publishable">
         <title>Metadati sulle informazioni di pubblicazione</title>
         <properties>
            <property name="gs:ToBePublished">
               <type>d:boolean</type>
               <mandatory>true</mandatory>
               <index enabled="true">
                  <atomic>true</atomic>
                  <stored>true</stored>
                  <tokenised>false</tokenised>
               </index>
            </property>
            <property name="gs:PublishDate">
               <type>d:date</type>
               <index enabled="true">
                  <atomic>true</atomic>
                  <stored>false</stored>
                  <tokenised>both</tokenised>
               </index>
            </property>
            <property name="gs:UnpublishDate">
               <type>d:date</type>
               <index enabled="true">
                  <atomic>true</atomic>
                  <stored>false</stored>
                  <tokenised>both</tokenised>
               </index>
            </property>
         </properties>
      </aspect>

As I said the configuration is not definitive because the requirement  I should implement is that PublishDate and UnpublishDate properties are read-only and managed by system as follows:

When a user edits a document and sets ToBePublished = True (False) automatically must be set (by the system, with a trigger, I do not know how …) PublishDate (UnublishDate) with the current date.
Does anyone have any suggestions?
Thanks in advance for your reply!
14 REPLIES 14

jpotts
World-Class Innovator
World-Class Innovator
It sounds like you need to set one property based on the value of another. You have several options for how to do this.

If you need the property to be set regardless of how the "toBePublished" property gets set (i.e., regardless of client, API, etc.), then the best bet is probably a behavior. A behavior is Java code that gets bound to your gsSmiley Tongueublishable aspect (you can use server-side JavaScript based behaviors but they are less common). When properties are updated, the behavior can check to see if the flag is true, and if it is, set the publish date.

Here is a tutorial on behaviors: http://ecmarchitect.com/images/articles/alfresco-behavior/behavior-article.pdf

Next, if you are using an action to set the toBePublished flag you can set the publish date property at that time. Actions are handy because they can be called from workflows, rules, from an API call, and from the user interface (either explorer or Share). Unlike the behavior, the integrity of your publish date field would only be guaranteed if the action is used consistently. If someone uses an API call to set the flag instead of your action, the date won't get set.

Here is a tutorial on actions: http://www.ecmarchitect.com/images/articles/alfresco-actions/actions-article.pdf

Actually, in my book, Alfresco Developer Guide, I show a custom UI action in Explorer called "Publish to Web" that may be doing something similar to what you are trying to do. It sets a flag and a publish date. My unpublish action sets the flag back to false. The source code for the book is freely-available here: http://code.google.com/p/alfresco-developer-guide/. I have ported this to a Share-based example, but haven't published that code yet. If you need it, let me know.

Finally, you could handle this completely through the client-side. If you are using Share as your UI, for example, you could write a custom control that would use client-side JavaScript to set the date field if the publish flag was changed. I don't have any good examples of this approach. It obviously has the drawback that if someone uses Explorer or an API call to change your flag, the date won't get set.

I suppose you could also use a form filter. Form filters intercept data before and after Share forms are rendered. So in your form filter you could look at the flag and then set the date. This has the same drawbacks as the client-side JavaScript approach.

I hope this has given you some options to consider and that you'll be able to determine which is best for your specific situation.

Jeff

joeforte
Champ in-the-making
Champ in-the-making
Hi, Jeff, thank you for your valuable suggestions.
If I understand the last two solutions you have listed are not suitable.
I would like to specify that the event that triggers the update of the fields is just the setting (manually, I stress) by the user of the property ToBePublished …

Of all the options that you told me I have studied in particular the solution using the javascript behavior and in my case, I suppose, the method that implements the behavior must be onUpdateProperties, right? So I wonder: the behavior triggered whenever the user updates any property of the document? It would be more efficient if the behavior will fire only when the user changes the property ToBePublished

so I suppose my bean will be something like:


<bean id="onChangePublishDate"
       class="org.alfresco.repo.policy.registration.ClassPolicyRegistration"
       parent="policyRegistration">
       <property name="policyName">
              <value>{http://www.alfresco.org}onUpdateProperties</value> <!– this is the method that triggers my behaviour… is it correct? –>
       </property>
       <property name="className">
             <value>????????</value>  <!– What should I put here? –>
       </property>
       <property name="behaviour">
              <bean class="org.alfresco.repo.jscript.ScriptBehaviour"
                    parent="scriptBehaviour">
                   <property name="location">
                          <bean class="org.alfresco.repo.jscript.ClasspathScriptLocation">
                               <constructorarg>
                                        <value>alfresco/extension/scripts/myscript.js</value>
                               </constructorarg>
                          </bean>
                   </property>
              </bean>
      </property>
</bean>

What to put in tag <value> of the property "className"?
I'm going the right way?

And myscript.js could be something like:

<import resource="classpath:alfresco/extension/scripts/myUpgradeScriptFields.js">
var scriptFailed = false;
// Have a look at the behaviour object that should have been passed
if (behaviour == null) {
    logger.log("The behaviour object has not been set.");
    scriptFailed = true;
}
// Check the name of the behaviour…. in my case is onUpdateProperties???
if (behaviour.name == null && behaviour.name != "onUpdateProperties") {
    logger.log("The behaviour name has not been set correctly.");
scriptFailed = true;
} else {
    logger.log("Behaviour name: " + behaviour.name);
}
// in my case I need to check the arguments??
if (behaviour.args == null) {
   logger.log("The args have not been set.");
   scriptFailed = true;
} else {

     logger.log("Calling update fields");
     updateFields(myArg); //method implemented in the myUpgradeScriptFields.js
} else {
     logger.log("The number of arguments is incorrect.");
     scriptFailed = true;
}
}

Apologize if I was prolix and thanks again for your feedback

jpotts
World-Class Innovator
World-Class Innovator
The className is for the type or aspect you are binding to. Here's an example from the Alfresco Developer Guide:

<bean id="onUpdateHrDoc" class="org.alfresco.repo.policy.registration.ClassPolicyRegistration" parent="policyRegistration">
        <property name="policyName">
            <value>{http://www.alfresco.org}onUpdateNode</value>
        </property>
        <property name="className">
            <value>{http://www.someco.com/model/content/1.0}hrDoc</value>
        </property>
        <property name="behaviour">
           <bean class="org.alfresco.repo.jscript.ScriptBehaviour" parent="scriptBehaviour">
                        <property name="location">
                                <bean class="org.alfresco.repo.jscript.ClasspathScriptLocation">
                                <constructor-arg>
                                   <value>alfresco/extension/scripts/onUpdateNode.js</value>
                        </constructor-arg>
                               </bean>
                        </property>
           </bean>
        </property>
    </bean>

Regarding your JavaScript, it looks like the right approach, although syntactically it may need some help. I think I see a problem with your final if-else block–are there two else's there?

Jeff

joeforte
Champ in-the-making
Champ in-the-making
Hi, Jeff

Regarding your JavaScript, it looks like the right approach, although syntactically it may need some help. I think I see a problem with your final if-else block–are there two else's there?

Obviously it was a hasty copy & paste…

But now I tried to run the behavior and I get the following error:

16:36:24,453 DEBUG [org.alfresco.repo.jscript.ScriptLogger] json form submission for item:
16:36:24,453 DEBUG [org.alfresco.repo.jscript.ScriptLogger]    kind = node
16:36:24,453 DEBUG [org.alfresco.repo.jscript.ScriptLogger]    id = workspace/SpacesStore/b2725bbb-98c4-4bc2-a1b5-bcd247eae99f
16:36:24,484 DEBUG [org.alfresco.repo.jscript.ScriptLogger] org.alfresco.scripts.ScriptException: 05130132 Failed to execute script 'alfresco/extension/scripts/onChangePublishDate.js': null
16:36:24,484 DEBUG [org.alfresco.repo.jscript.ScriptLogger] Returning 500 status code

And my bean is:

<bean id="onChangePublishDateNode"
           class="org.alfresco.repo.policy.registration.ClassPolicyRegistration"
           parent="policyRegistration">
           <property name="policyName">
                  <value>{http://www.alfresco.org}onUpdateProperties</value>
           </property>
           <property name="className">
                 <value>{http://giunti.noze.it/model/content/1.0}properties</value>
           </property>
           <property name="behaviour">
                  <bean class="org.alfresco.repo.jscript.ScriptBehaviour"
                        parent="scriptBehaviour">
                       <property name="location">
                              <bean class="org.alfresco.repo.jscript.ClasspathScriptLocation">
                                   <constructor-arg>
                                            <value>alfresco/extension/scripts/onChangePublishDate.js</value>
                                   </constructor-arg>
                              </bean>
                       </property>
                  </bean>
          </property>
    </bean>

what's the problem for you?

thanks again

joeforte
Champ in-the-making
Champ in-the-making
Ok I managed to start the script. It seems that it does not digest the import directive:

<import resource="classpath:alfresco/extension/script/changeDate.js">

…But it seems a little strange…  :roll:

jpotts
World-Class Innovator
World-Class Innovator
Did you name your directory "script" or "scripts"? You've got "script" in the import in your latest post but in an earlier post it looks like you are using "scripts".

Jeff

joeforte
Champ in-the-making
Champ in-the-making
Ok, yet another naive, I corrected.
But now there's a little more serious problem: the parameters before and after coming to the script both null… I have seen there is a topic which opened two years ago by a guy who had the same problem but never received a response…

..and now?

jpotts
World-Class Innovator
World-Class Innovator
From looking at your spring config, it looks like you've specified your class name as:
          
<property name="className">
                 <value>{http://giunti.noze.it/model/content/1.0}properties</value>
           </property>

I was expecting that to be a type or an aspect. Do you have a type or an aspect named "{http://giunti.noze.it/model/content/1.0}properties"?

Jeff

joeforte
Champ in-the-making
Champ in-the-making
From looking at your spring config, it looks like you've specified your class name as:
          
<property name="className">
                 <value>{http://giunti.noze.it/model/content/1.0}properties</value>
           </property>

I was expecting that to be a type or an aspect. Do you have a type or an aspect named "{http://giunti.noze.it/model/content/1.0}properties"?

Jeff

I forgot to specify that I changed some things in the configuration:

My custom context contains the following code:

<bean id="giuntiDictionaryModelBootstrap.dictionaryBootstrap"
      parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
      <property name="models">
         <list>
            <value>alfresco/extension/giunti-model.xml</value>
         </list>
      </property>
   </bean>

And my custom aspect contains contains the following namespace:


<namespaces>
      <namespace uri="http://giunti.noze.it/model/content/1.0" prefix="gs" />
   </namespaces>

and the following description:


<aspect name="gs:properties">
<title>…. </title>
<properties>…

</properties>

Is it correct?