Welcome to the first post in my Alfresco RM 2.0 - Tips, Tricks, and Examples series.

In this post I will describe the process of creating a new custom record type in RM 2.0, using the existing DOD5015 record types as examples. I'll also show you how to get rid of the DOD5015 record types that are installed by default, so that you'll end up with a clean RM fully customized for your organization, and will teach you how to configure Share to show the properties and associations for your custom record type in the Edit Metadata page.

Getting started

First, of course, you need to install RM 2.0. To do this, apply the RM 2.0 amps to your existing Alfresco installation and restart your Alfresco server. Once your server is back up and running, log into Share as an Alfresco administrator and add the Records Management dashlet to your dashboard. If you've never used RM before, you should push the Load Test Data button and then spend some time in the Records Management Site to see what RM is all about. Note that you can only have one Records Management Site in Alfresco, so if you load the test data you'll need to delete it later on when you get rid of the default DOD5015 RM model.

Now that you've got a working Alfresco RM 2.0 installation, it's time to start customizing things to reflect the needs of your organization or customer. For the purposes of this blog post, I want to end up with an RM install that contains only a single record type called a Tribloom Contract. A Tribloom Contract has the following properties:

  • Expiration Date (date - mandatory)
  • Critical Contract (a text property that is displayed as a select control with the options YES and NO)
  • Expiration Notification Email Sent (boolean property that reflects whether an email has been sent to the contract owner that the contract will expire soon)
  • Contract Owner (an association with cm:person that allows a single value - mandatory)

Creating the custom record type

To create your custom record type, you need to start by creating a custom model for your RM installation. You can always start from scratch if you want, but I think the easiest way to do this is to copy the dod5015 folder under /webapps/alfresco/WEB-INF/classes/alfresco/module/org_alfresco_module_rm/dod5015 and paste it back into the same location with a name that makes sense for your organization. For this blog post example I ended up with /webapps/alfresco/WEB-INF/classes/alfresco/module/org_alfresco_module_rm/tribloom.

In the new folder, first delete the files DODExampleFilePlan.acp and DODExampleFilePlan.xml. These files define sample File Plans based on the DOD5015 model, and they aren't relevant to your new custom record type. Next, rename the remaining files in your folder to make sense for you. I ended up with the following:

/tribloom/tri-rm-context.xml

/tribloom/tri-rm-model.properties

/tribloom/tribloom-rm-model.xml

Now let's open up those files and make the changes we need to make within them.

/tribloom/tri-rm-context.xml

This is the Spring configuration file that defines the dictionaryModelBootstrap bean that will load your custom RM model. Modify the value entries for the models and labels properties to match your new model file and properties file.

<!-- Bootstrap Records Management Models -->
<bean id="org_alfresco_module_tribloom_tribloomdictionaryBootstrap"parent="dictionaryModelBootstrap" depends-on="dictionaryBootstrap">
<property name="models">
<list>
<value> alfresco/module/org_alfresco_module_rm/tribloom/tribloom-rm-model.xml</value>
</list>
</property>
<property name="labels">
<list>
<value> alfresco/module/org_alfresco_module_rm/tribloom/tri-rm-model</value>
</list>
</property>

</bean>

/tribloom/tri-rm-model.properties

This file defines property strings for the RM model. You can delete all the property entries here; these entries are all used by the DOD5015 model and not relevant to the new custom record type you're creating. If you find that you need to define new properties later on, do it within this file.

/tribloom/tribloom-rm-Model.xml

The file contains your custom RM model definition, which includes all your custom RM types and their properties. Since you're starting from the DOD5015 model file, the first thing you want to do is modify the model to use a namespace that makes sense for you. I use "tri", short for Tribloom, in this example. Next, add a new aspect representing your record type, including whatever properties you want. Last, delete everything from the DOD5015 model that you don't want to include in your customized RM install. I didn't want to keep anything from the default model, so I deleted everything after adding my new record type.

Below is the entirety of my model file, which contains a single custom record type with three properties and an association.

<?xml version="1.0" encoding="UTF-8"?>
<!-- Definition of Tribloom RM Model -->
<model name="tri:tri" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<!-- Meta-data about the model -->
<description> Tribloom RM Model</description>
<author> Laura Patterson</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"/>
<!-- Import Alfresco Content Domain Model Definitions -->
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys" />
<!-- Import Alfresco Records Management Model Definitions -->
<import uri="http://www.alfresco.org/model/recordsmanagement/1.0" prefix="rma" />
</imports>

<!-- Records Management Namespace -->
<namespaces>
<namespace uri="http://www.alfresco.org/model/tri-rm/1.0" prefix="tri"/>
</namespaces>

<aspects>
<aspect name="tri:contractRecord">
<title> Tribloom Contract</title>
<parent> rma:recordMetaData</parent>
<properties>
<property name="tri:expirationDate">
<title> Expiration Date</title>
<type> d:date</type>
<mandatory> true</mandatory>
</property>
<property name="tri:criticalContract">
<title> Critical Contract</title>
<type> d:text</type>
<constraints>
<constraint name="tri:criticalContractList" type="LIST">
<parameter name="allowedValues">
<list>
<value> Yes</value>
<value> No</value>
</list>
</parameter>
</constraint>
</constraints>
</property>
<property name="tri:emailSent">
<title> Expiration Notification Email Sent</title>
<type> d:boolean</type>
<protected>true</protected>

<mandatory> false</mandatory>

</property>
</properties>

<associations>
<association name="tri:contractOwner">
<title>Contract Owner</title>
<source>
<mandatory> true</mandatory>
<many> true</many>
</source>
<target>
<class> cm:person</class>
<mandatory> false</mandatory>
<many> false</many>
</target>
</association>
</associations>
<mandatory-aspects>
<aspect> rma:filePlanComponent</aspect>
</mandatory-aspects>
</aspect>
</aspects>

</model>

As you can see, a custom record type for RM is defined as an aspect with the parentrma:recordMetaData and a mandatory-aspects entry of rma:filePlanComponent. Beyond that, creating the custom type is the same as any other Alfresco content modeling. You can use constraints and associations (but you'll need to take an extra step to get your associations to show up in the right section of the property sheet - more on that below), and if you mark properties as mandatory, they'll need to be populated before a file of this type can be declared as a record.

At this point you've created a new RM model containing a custom record type and set up a bootstrap Spring bean to load the custom model. If you restart your server now, though, you'll still only see the default DOD5015 record types when you try to add a new record.

Loading the custom record type - and NOT loading the DOD5015 record types

In order to load your new model and NOT load the DOD5015 model, you also need to modify/tomcat/webapps/alfresco/WEB-INF/classes/alfresco/module/org_alfresco_module_rm/module-context.xml. Note: Before you do this, you should delete the DOD5015 test data in the file plan, especially if you played with the RM features like record freezing after you loaded the data; you'll be unable to delete things that are frozen once you're no longer importing the dod5015 model.

In order to stop loading the DOD5015 model, you need to comment out or delete the import entry for dod5015-context.xml in module-context.xml. In order to load your new custom model, you need to add a new import entry for the new model file. The changes to my module-context.xml look like this:

<!-- Import DOD 5015 --><!-- Tribloom: Do not import DOD 5015, import Tribloom module instead -->
<!-- <import resource="classpath:alfresco/module/org_alfresco_module_rm/dod5015/dod5015-context.xml"/> -->

<!-- Import Tribloom -->
<import resource="classpath:alfresco/module/org_alfresco_module_rm/tribloom/tribloom-rm-context.xml"/>

After saving the changes to module-context.xml, you can restart your Alfresco server and you'll start to see your custom record type in action. Go into the File Plan in the RM site and press the File button. Select to file an Electronic record, and Tribloom Contract will be the only record type available in the dialog box. (Remember that you can only add files within Folders, so you may need to create a Category with a Folder inside it before you can upload a file.) If you press the Tribloom Contract button and upload a file, your new undeclared record will have a type of Tribloom Contract.

Upload File dialog

Making your custom metadata show up in the property sheet

Although you can upload a Tribloom Contract into your RM File Plan, your work isn't done yet. First, if you go into the Edit Metadata page for your file, you'll see the default properties of Name, Title, etc, and you'll see a section containing Record metadata…but you won't see a section containing the custom Tribloom Contract metadata. Even worse, after you fill out the mandatory properties under the Record section and push the Save button, you'll still see this dialog if you try to declare your new Tribloom Contract as a record:

Could not delcare record error

This dialog shows up because the Expiration Date property on Tribloom Contract is declared as mandatory in our model, and Alfresco RM 2.0 won't allow records to be declared if any of their mandatory properties are not populated.

To make your custom metadata show up in the Edit Metadata page, the first thing you need to do is copy the file /webapps/share/WEB-INF/classes/alfresco/dod-form-config.xml and paste it into the same directory with a name that makes sense for your organization. For this example, my form config file is /webapps/share/WEB-INF/classes/alfresco/tribloom-rm-form-config.xml.

In your new form config file, delete everything except one of the set lines within the config evaluator for rm-kind with condition RECORD. You shouldn't need the config evaluator that's included for backwards compatibility with RM 1.0 if this is a new RM 2.0 install. For the one set line you kept, modify the id value to match the model definition for your record type following the format below (rm-metadata-yourNamespace-yourAspectNameWithoutNamespace). This is what allows the Edit Metadata page to include a labeled panel containing the metadata for your custom record type.

<set id="rm-metadata-tri-contractRecord" label="Tribloom Contract" appearance="panel" />

Much like loading your custom model in Alfresco, in order for your form config file to be picked up by Share you'll need to add an entry for it in the config bootstrap bean. Open up/webapps/share/WEB-INF/classes/alfresco/web-extension/rm-context.xml and add a new value entry for the rm.custom.config bean as follows. While you're there, you might as well also delete the value entry for dod-form-config.xml, since it's no longer needed.

<value>classpath:alfresco/tribloom-rm-form-config.xml</value>

If you restart your Alfresco server and view the metadata for the file you previously uploaded, you'll see a new Tribloom Contract section at the bottom of the Edit Metadata page. This section contains three properties, including the mandatory Expiration Date property. The Critical Contract property appears as a select control with NO and YES values. The Expiration Notification Email Sent property is read-only, as indicated by setting its protected value to true in the model. Populate the Expiration Date and press the Save button, and you'll now be able to declare the file as a record. You're done creating your custom record type!

Well, almost.

But what about the Contract Owner association?

Remember, the Tribloom Contract record type has three properties and one association. The properties are doing great now in the Edit Metadata page, but there's no sign of the Contract Owner association. In order to make the Contract Owner association show up in the Edit Metadata page, you need to make a few more additions to tribloom-rm-form-config.xml.

First, you need to add a field-visibility entry for the Contract Owner field:

<field-visibility>
<show id="tri:contractOwner"/>
</field-visibility>

If you restart your server now, you'll see the Contract Owner association in your Edit Metadata page…but it will be up at the top in the default metadata section instead of at the bottom in the Tribloom Contract section. It also won't be mandatory, and we need it to be mandatory*.

To fix both of those problems, add the following field entry to the appearance section of your form config. This field entry explicitly includes the Contract Owner field in the Tribloom Contract set, so it will be added to the Tribloom Contract panel in the Edit Metadata page. Setting the mandatory property to true requires the user to populate the association before the Save Button on the Edit Metadata page will become enabled.

<field id="tri:contractOwner" set="rm-metadata-tri-contractRecord" mandatory="true"/>

My final tribloom-rm-form-config.xml looks like this:

<alfresco-config>

<config evaluator="rm-kind" condition="RECORD">
<forms>
<form>
<field-visibility>
<show id="tri:contractOwner"/>
</field-visibility>

<appearance>
<!-- Tribloom extended meta-data -->
<set id="rm-metadata-tri-contractRecord" label="Tribloom Contract"appearance="panel" />
<field id="tri:contractOwner" set="rm-metadata-tri-contractRecord"mandatory="true" />
</appearance>
</form>
</forms>
</config>

</alfresco-config>

Restart your Alfresco server after making those changes, and the Tribloom Contract section of the Edit Properties page will now look just the way we want it to:

Tribloom Contract metadata panel

* A side note about mandatory associations. You really, really don't want to make the target of your association mandatory in your model unless you plan to populate it programmatically. (This is an Alfresco thing, not an RM thing.) If you make the target mandatory in the model and then try to upload a file of Tribloom Contract type, Alfresco will throw an error and not allow you to upload the file. The problem is that the target of the association isn't populated since the user hasn't had a chance to go into the Edit Metadata page and set it yet, but the model says the value is mandatory. Alfresco throws its hands in the air and says NO I CAN'T DO THIS and you can't upload your file. Instead of setting the association target as mandatory in the model, a better choice is to set the association as mandatory in your form config appearance section. This is probably the behavior you want anyway: once the user goes into the Edit Metadata page, the association target must be populated before the metadata can be saved. This is the behavior I want with the Contract Owner association, at any rate**.

** One small caveat here: if you set the association as mandatory in Share rather than the model, technically you'll still be able to declare a file as a record without that association being populated. For example, before we made the Contract Owner field visible via our custom form config file, we were able to declare a file as a record without it having a Contract Owner value. However, as long as the association shows up in the Edit Metadata page, Share won't let you save the metadata without the association being populated. Therefore you won't actually be able to declare the file as a record without the association being populated.

Now you're really done

If you followed the steps outlined in this blog post, you now have an Alfresco RM 2.0 installation that allows users to add a custom record type of Tribloom Contract to their file plan. This custom record type has three properties, including one that is mandatory, one that is read-only, and one that is displayed as a select control in the form, and it also has an association to cm:person. You've learned how to load the model containing your custom record type as well as NOT load the default dod5015 model, and you've learned how to configure Share to display the properties and association for your custom record type in the Edit Metadata page.

If you need more custom record types, just create additional aspects in your model file and add the necessary set entries and any other form configuration to your form config file to ensure that the custom properties for each record type appear in the Edit Metadata. You can handle associations, mandatory properties, select controls populated by constraints, and read-only properties.

In order to use these changes in the real world instead of just playing around with them inside of Tomcat, you'll want to store them in source control and package them up as amps that you can deploy on top of an Alfresco RM 2.0 installation, of course, but the important thing is that now you know what changes you need to make.

From here on out, you're in complete control of what record types show up in your Alfresco RM 2.0 world.


Loading Conversation