Archive for the ‘alfresco tech’ Category

Disabling Auditable Properties from Being Set Automatically

Sunday, May 3rd, 2009

When performing content ingestion, it is often needed to set some system properties that are governed by the Auditable Aspect. These properties are cm:created, cm:creator, cm:modified, cm:modifier. In 3.0 and 3.1, there is no explicit option to turn these off. If this issue affects you, please vote for this JIRA ticket, but in the meantime, here is a way to get around this when you need to disable automatic setting of these properties temporarily.

Note: we are using some trickery here, and doing things that aren’t typically recommended, so please be very careful and test things out in your environment. This worked for me on Alfresco 3.0SP1.

The auditing properties are being set pretty deep inside the infrastructure code (class HibernateNodeDaoServiceImpl). The code checks whether Auditable aspect is applied, and if so, it sets these properties explicitly. One way to disable this is by modifying the code. The way to do it more cleanly is by temporarily changing contentModel.xml. Auditable aspect applied is a mandatory aspect on cm:object, which is parent of cm:content.

Step 1 – Disabling Automatic Setting of Auditable Properties

So my solution is to remove Auditable as a mandatory aspect and to add those properties to cm:object directly. This is the new definition of cm:object.

<type name=”cm:cmobject”>

<title>Object</title>

<parent>sys:base</parent>

<properties>

<property name=”cm:name”>

<title>Name</title>

<type>d:text</type>

<mandatory enforced=”true”>true</mandatory>

<constraints>

<constraint ref=”cm:filename” />

</constraints>

</property>

<!–temporary added properties to go around auditable –>

<property name=”cm:created”>

<title>Created</title>

<type>d:datetime</type>

</property>

<property name=”cm:creator”>

<title>Creator</title>

<type>d:text</type>

</property>

<property name=”cm:modified”>

<title>Modified</title>

<type>d:datetime</type>

</property>

<property name=”cm:modifier”>

<title>Modifier</title>

<type>d:text</type>

</property>

<property name=”cm:accessed”>

<title>Accessed</title>

<type>d:datetime</type>

</property>

</properties>

<!—- Disable Auditable Aspect

<mandatory-aspects>

<aspect>cm:auditable</aspect>

</mandatory-aspects>

–>

</type>

Additionally, for convenience, it’s a good idea to not make these protected, or enforce them as being mandatory, as they are on the original Auditable aspect. As you can see, we commented out cm:auditable as mandatory aspect on this type, which means the code that sets these properties automatically will not get triggered.

Step 2 – Show Properties in the User Interface

The next step is cosmetic – we need to make these properties visible in our UI so it’s easier to test. For that, you will need to edit CONFIGROOT web-client-config-properties.xml. Add the auditable properties to “content” evaluator:

<config evaluator=”node-type” condition=”content”>

<property-sheet>

<show-property name=”creator” />

<show-property name=”created” />

<show-property name=”modifier” />

<show-property name=”modified” />

This will allow you to see these in the UI.

Step 3 – Set Properties, Migrate Content, Perform Bulk Load, etc.

After a server restart, you have now disabled the automatic setting of properties. You can either set them programmatically (and your changes will no longer get intercepted), or manually through the UI.

Edit Auditable properties

Edit Auditable properties

Note: This is an all or nothing operation – you can’t have it automatically set some properties but not others (to do it you’d have to do metadata extraction or some kind of event handler). This is why this is usually a temporary step as you are loading or migrating content.

After you are done with the content load, the next step is re-enable original model to ensure consistency. You also have a bunch of nodes that don’t have Auditable Aspect applied, so we need to reapply it.

Step 4 – Apply Auditable Aspect to Migrated Content

First, you need to revert to the original content model. To apply auditable aspect to many nodes, you typically write a JavaScript script that walks through the nodes and adds Auditable Aspect.

For applying Auditable aspect manually, you’ll have to add some code to CONFIGROOTweb-client-config.xml so it shows u in Add Aspect action.

<config evaluator=”string-compare” condition=”Action Wizards”>


<!– and the has-aspect condition –>

<aspects>
<aspect name=”generalclassifiable”/>

<aspect name=”complianceable”/>

<aspect name=”dublincore”/>

<aspect name=”auditable”/>

<aspect name=”effectivity”/>

<aspect name=”summarizable”/>

<aspect name=”versionable”/>

<aspect name=”templatable”/>

<aspect name=”emailed”/>

<aspect name=”emailserver:aliasable”/>

<aspect name=”taggable”/>

</aspects>

Another possible solution that might preclude this is to have a rule that automatically adds the Auditable aspect as you create nodes, but I haven’t tested that yet.

Step 5 – Restore original state of contentModel.xml and web-client-config-properties.xml

To get everything back to a consistent state, you now have to restore your original contentModel and UI properties. Because all nodes now have auditable aspect applied, as well as the properties that need to exist do in fact exist, Alfresco will now be able to pick it up from there and manage these properties the way it always does.

XML Metadata Extraction for WCM

Monday, December 1st, 2008

While the XSDs in the WCM (AVM) are the equivalent of content models in DM, there is no effective way to search them. More specifically, it’s useful to be able to search based on a specific metadata elements in the generated XMLs, something that you need to do frequently in highly dynamic sites. In this post, we’ll discuss the sample I created for this that’s in the content community here (registration required).

In this example, I have a WCM content type defined through XSD press_release.xsd.  I want to extract some metadata from it, for example, expiration date of the press release. The extraction process works similarly to the way things function on the DM side, with some gotchas. When extracting metadata, you need somewhere (properties) to store it.

For WCM (where all the XML nodes are stored as wcm:avmplaincontent type), is by creating an aspect with the properties that you want to extract.   This is important – it has to be an aspect. This aspect will automatically get applied appropriately, as we’ll see later. In the included example, I have a XSD that creates a press release.  I want to extract and index three properties – abstract (string), expiration date (date), and numtimes (int). Here is the code (I removed all the indexing properties for simplicity)

<aspects>

<aspect name="my:press_release_metadata">

<title>Sample Aspect for WCM – Press Release</title>

<properties>

<property name="my:abstract">

<type>d:text</type>

</property>

<property name="my:expiration_date">

<type>d:datetime</type>

</property>

<property name="my:numtimes">

<type>d:int</type>

</property>

</properties>

</aspect>

</aspects>

You’ll also need to expose your aspect properties in the UI through web-client-config-custom.xml

<config evaluator="aspect-name" condition=" my:press_release_metadata">

<property-sheet>

<show-property name="my:abstract" />

<show-property name="my:expiration_date" />

<show-property name="my:numtimes" />

</property-sheet>

</config>

Once I have the aspect in my content model (customModel.xml, which I introduce to the Data Dictionary through custom-model-context.xml), I can start configuring extraction process as outlined in wcm-xml-metadata-extracter-context.xml.  There are two key sections:

  1. Selector section (extracter.xml.sample.selector.XPathSelector bean), which looks inside the XML and maps it to the correct Extractor Bean.  Since all the XForms of any type get saved as XML, we need to select the appropriate one (in this case pr:press_release). This configuration associates the specific XForm with a specific extraction definition.

    <bean id="extracter.xml.sample.selector.XPathSelector" class="org.alfresco.repo.content.selector.XPathContentWorkerSelector" init-method="init"> <property name="workers"> <map> <entry key="/pr:press_release"> <ref bean="extracter.xml.sample.AlfrescoCustomModelMetadataExtracter" /> </entry> </map> </property> </bean>

  2. Extractor bean for each of the Web Content Types you defined.  These have two parts:

    A. xpathMappingProperties – take an xpath expression that can extract value out of XML file and store it into internal Map.  So, for example, the abstract property can be found through xpath expression "/press_release/abstract".  It then gets stored into "abstract" internal map property.

    <prop key="abstract">/press_release/abstract</prop>

    Note that we have to also specify namespace so Alfresco can resolve them appropriately:   

    <prop key="namespace.prefix.pr">http://www.alfresco.org/alfresco/pr</prop>

B. mappingProperties – takes the properties out of internal map, and puts it into the specified data dictionary property.  Here is the key – the extractor finds the corresponding aspect and automatically ("automagically") adds it to the Alfresco node. Before setting it, it checks for the target data type, and attempts to convert it to that type.  In the example we are using, it takes out the internal map property "abstract" and sets it to property my:abstract. In this case the property is a string, so no conversion is really required.

       <prop key="abstract">my:abstract</prop>

Note on Converting Dates: When I did this initially, I got an exception for converting dates.  This is because the XForms store dates in the format of 2008-04-28, and the automatic cast did not work.  To remedy that, I added a configuration setting where I specified the correct date format for the extractor to use: <property name="supportedDateFormats"> <list> <value>yyyy-MM-dd</value> </list> </property> Note, that metadata extraction runs when you create content (in the user sandbox).   They key here is that the aspect gets applied automatically by the extraction process – you don’t need to make sure it’s added. You don’t even see mention of the aspect anywhere in the configuration files. This is what is should look like in the example:


The Lucene indexing will happen when you promote the content to the staging sandbox.

The indexing is governed by the settings on the properties you define on properties of the aspects (namely <index> element):

<property name="my:expiration_date">

<type>d:datetime</type>

<index enabled="true">

<atomic>true</atomic>

<stored>false</stored>

<tokenised>false</tokenised>

</index>

</property>

You cannot search based on these properties from the Search UI, since this relates to the WCM content, but you can query this using the Node Browser for testing, or, of course, the ultimate goal is likely to expose this through some web scripts.

Dynamic Models in 3.0

Tuesday, November 18th, 2008

One of the features in 3.0 that I am particular excited about is Dynamic Models (though they actually have been around since 2.9).  It allows changing the content model without having to restart the server.   While implemented to provide Multi-Tenancy capabilities, I am excited about it because it gets us much closer to having ability to have users create content models through UI.  In addition to dynamic modeling capability, you can now make some UI customizations, upload resource bundles, and add workflows, all without having to restart the server.  This is not only a great feature, but will save developers a lot of time.

To learn more about Dynamic Models, check out the wiki page, and for a quick overview – see this great Screencast that J.M. Pascal created showing the Dynamic Models functionality.  Check it out, as well as his blog in general – he has a bunch of fun presentation about some other Alfresco concepts as well!


Alfresco Home | Legal | Privacy | Accessibility | Site Map | RSS  RSS

© 2012 Alfresco Software, Inc. All Rights Reserved.