Tuesday, November 24, 2009

Working with Custom Content Types

Alfresco is a flexible platform for developing content management applications. The first step in the process of designing a custom content management application is creating the content model.

A content model describes the data being stored in the repository. The content model is critical—without it, Alfresco would be little more than a file system.

Modeling basics
A content model describes the data being stored in the repository. The content model is critical—
without it, Alfresco would be little more than a file system. Here is a list of key information the content

model provides Alfresco:
● Fundamental data types and how those data types should be persisted to the database. For
example, without a content model, Alfresco wouldn't know the difference between a String and
a Date.
● Higher order data types like “content” and “folder” as well as custom content types like
“Standard Operating Procedure” or “Contract”.
● Outofthebox aspects like “auditable” and “classifiable” as well as custom aspects like “rateable”
or “commentable”.

Properties (or metadata) specific to each content type.
● Constraints placed on properties (such as property values that must match a certain pattern or
property values that must come from a specific list of possible values).
● How to index content for searching.
● Relationships between content types.

Alfresco content models are built using a small set of building blocks: Types, Properties, Property
types, Constraints, Associations, and Aspects

Types are like types or classes in the object-oriented world. They can be used to model business objects,
they have properties, and they can inherit from a parent type. “Content”, “Person”, and “Folder” are
three important types defined outofthebox.
Custom types are limited only by your imagination and business requirements. Examples include things like “Expense Report”, “Medical Record”, “Movie”,“Song”, and “Comment”.
Note that types, properties, constraints, associations, and aspects have names. Names are made unique
across the repository by using a namespace specific to the model.The namespace has an abbreviation.

So, for example, at Optaros we might define a custom model which declares a namespace with the URI
of “http://www.optaros.com/model/content/1.0” and a prefix of “opt”. Any type defined as part of that
model would have a name prefixed with “opt:”. We'll talk more about how models are actually defined
using XML, but I wanted to introduce the concept of namespaces and prefixes so you would know what
they are when you see them. Using namespaces in this way helps prevent name collisions when content
models are shared across repositories.

Properties are pieces of metadata associated with a particular type. For example, the properties of an
Expense Report might include things like “Employee Name”, “Date submitted”, “Project”, “Client”,
“Expense Report Number”, “Total amount”, and “Currency”. The Expense Report might also include a
“content” property to hold the actual expense report file (maybe it is a PDF or an Excel spreadsheet, for

Property types

Property types (or data types) describe the fundamental types of data the repository will use to store properties. Examples include things like strings, dates, floats, and booleans. Because these data types
literally are fundamental, they are pretty much the same for everyone so they are defined for us outofthebox.
(If you wanted to change the fact that the Alfresco datatype “text” maps to your own custom
class rather than java.lang.String, you could, but let's not get ahead of ourselves).

Constraints can optionally be used to restrict the value that Alfresco will store in a property. There are
four types of constraints available: REGEX, LIST, MINMAX, and LENGTH. REGEX is used to make

sure that a property value matches a regular expression pattern. LIST is used to define a list of possible
values for a property. MINMAX provides a numeric range for a property value. LENGTH sets a
restriction on the length of a string.
Constraints can be defined once and reused across a model. For example, outofthebox,
makes available a constraint named “cm:filename” that defines a regular expression constraint for file
names. If a property in a custom type needs to restrict values to those matching the filename pattern,
the custom model doesn't have to define the constraint again, it simply refers to the “cm:filename”

Associations define relationships between types. Without associations, models would be full of types
with properties that store “pointers” to other pieces of content. Going back to the expense report
example, we might want to store each expense as an individual object. In addition to an Expense Report
type we'd also have an Expense type. Using associations we can tell Alfresco about the relationship
between an Expense Report and one or more Expenses.
Associations come in two flavors: Peer Associations and Child Associations. (Note that Alfresco refers
to Peer Associations simply as “Associations” but I think that's confusing so I'll refer to them with the
“Peer” distinction). Peer Associations are just that—they define a relationship between two objects but
neither is subordinate to the other. Child Associations, on the other hand, are used when the target of
the association (or child) should not exist when the source (or parent) goes away. This works like a
cascaded delete in a relational database: Delete the parent and the child goes away.
An outofthebox association that's easy to relate to is “cm:contains”. The “cm:contains” association
defines a Child Association between folders (“cm:folder”) and all other objects (instances of “sys:base”
or its child types). So, for example, a folder named “Human Resources” (an instance of “cm:folder”)
would have a “cm:contains” association between itself and all of its immediate children. The children
could be instances of custom types like Resume, Policy, or Performance Review.

Another example might be a “Whitepaper” and its “Related Documents”. Suppose that a company
publishes whitepapers on their web site. The whitepaper might be related to other documents such as
product marketing materials or other research. If the relationship between the whitepaper and its related
documents is formalized it can be shown in the user interface. To implement this, as part of the
Whitepaper content type, you'd define a Peer Association. You could use “sys:base” as the target type
to allow any piece of content in the repository to be associated with a Whitepaper or you could restrict
the association to a specific type.

Before we talk about Aspects, let's first consider how inheritance works and the implications on our
content model. Suppose we are going to use Alfresco to manage content to be displayed in a portal
(quite a common requirement, by the way). Suppose further that only a subset of the content in our
repository is content we want to show in the portal. And, when content is to be displayed in the portal,
there are some additional pieces of metadata we need to capture. A simple example might be that we
want to know the date and time a piece of content was approved to be shown in the portal.
Using the content modeling concepts discussed so far, we would have only two options. First, we could
define a root content type with the “publish date” property. All subsequent content types would inherit
from this root type thus making the publish date available everywhere. Second, we could individually
define the publish date property only in the content types we knew were going to be published to the
Neither of these are great options. In the first option, we would wind up with a property in eachandevery
piece of content in the repository that may or may not ultimately be used which can lead to
performance and maintenance problems. The second option isn't much better for a few reasons. First, it
assumes we know which content types we want to publish in the portal ahead of time. Second, it opens
up the possibility that the same type of metadata might get defined differently across content types.
Last, it doesn't give us an easy way to encapsulate behavior or business logic we might want to tie to the
publish date.
As you have probably figured out by now, there is a third option that addresses these issues: Aspects.
Aspects allow us to “crosscut”
our content model with properties and associations by attaching them to
content types (or even specific instances of content) when and where we need them.
Going back to the portal example, we would define a “Portal Displayable” aspect with a publish date
property. The aspect would then be added to any piece of content, regardless of type, that needed to be
displayed in the portal.

Custom Behavior
You may find that your custom aspect or custom type needs to have behavior or business logic
associated with it. For example, every time an Expense Report is checked in you want to recalculate the
total by iterating through the associated Expenses. One option would be to incorporate this logic into
rules or actions in the Alfresco web client or your custom web application. But some behavior is so
fundamental to the aspect or type that it should really be “bound” to the aspect or type and invoked any
time Alfresco works with those objects. I'll show how to do this in a future article, but you should know
that associating business logic with your custom aspects and types (or overriding outofthebox
behavior) is possible.
Content Modeling Best Practices
Now that you know the building blocks of a content model, it makes sense to consider some best
practices. Here are the top ten:
1. Don't change Alfresco's outofthebox content model. If you can possibly avoid it, do not
change Alfresco's outofthebox content model. Instead, extend it with your own custom content model. If requirements call for several different types of content to be stored in the repository, create a content type for each one that extends from cm:content or from an enterprisewide root content type.
2. Consider implementing an enterprisewide root type. Although the need for a common ancestor
type is lessened through the use of aspects, it still might be a good idea to define an enterprisewide
root content type from which all other content types in the repository inherit if for no other
reason than it gives content managers a “catchall” type to use when no other type will do.
3. Be conservative early on by adding only what you know you need. A corollary to that is prepare
yourself to blow away the repository multiple times until the content model stabilizes. Once you
get content in the repository that implements the types in your model, making model additions
is easy, but subtractions aren't. Alfresco will complain about “integrity errors” and may make
content inaccessible when the content's type or properties don't match the content model
definition. When this happens to you (and it will happen) your options are to either 
(1) leave the old model in place,
(2) attempt to export the content, modify the ACP XML file, and reimport,
or (3) drop the Alfresco tables, clear the data directory, and start fresh. As long as everyone on
the team is aware of this, option three is not a big deal in development, but make sure
expectations are set appropriately and have a plan for handling model changes once you get to
production. This might be an area where Alfresco will improve in future releases, but for now it
is something you have to watch out for.
4. Avoid unnecessary content model depth. I am not aware of any Alfresco Content Modeling
Commandments that say, “Thou shall not exceed X levels of depth in thine content model lest
thou suffer the wrath of poor performance” but it seems logical that degradation would occur at
some point. If your model has several levels of depth beyond cm:content, you should at least do
a proofofconcept with a realistic amount of data, software, and hardware to make sure you
aren't creating a problem for yourself that might be very difficult to reverse down the road.
5. Take advantage of aspects. In addition to the potential performance and overhead savings
through the use of aspects, aspects promote reuse across the model, the business logic, and the
presentation layer. When working on your model you find that two or more content types have
properties in common, ask yourself if those properties are being used to describe some higherlevel
characteristic common across the types that might better be modeled as an aspect.
6. It may make sense to define types that have no properties or associations. You may find
yourself defining a type that gets everything it needs through either inheritance from a parent
type or from an aspect (or both). In those cases you might ask yourself if the “empty” type is
really necessary. In my opinion, it should at least be considered. It might be worth it just to
distinguish the content from other types of content for search purposes, for example. Or, while
you might not have any specialized properties or associations for the content type you could
have specialized behavior that's only applicable to instances of the content type.
7. Remember that folders are types too. Like everything else in the model, folders are types which
means they can be extended. Content that “contains” other content is common. In the earlier
expense report example, one way to keep track of the expenses associated with an expense
report would be to model the expense report as a subtype of cm:folder.
8. Don't be afraid to have more than one content model XML file. We haven't talked about exactly
how content models are defined yet, but when it is time to implement your model, keep this in
mind: It might make sense to segment your models into multiple namespaces and multiple
XML files. Names should be descriptive. Don't deploy a model file called “customModel.xml”
or “myModel.xml”.
9. Implement a Java class that corresponds to each custom content model you define. Within each
content model Java class, define constants that correspond to model namespaces, type names,
property names, aspect names, etc. You'll find yourself referring to the “Qname” of types,
properties, and aspects quite often so it helps to have constants defined in an intuitive way.
10.Use the source! The outofthebox content model is a great example of what's possible. The
forumModel and recordsModel have some particularly useful examples. In the next section I'll
tell you where the model files live and what's in each so you'll know where to look later when
you say to yourself, “Surely, the folks at Alfresco have done this before”.

Custom Model Example

Define the aspect in a file called  custom-model.xml  that goes 
Login to Alfresco and Goto  Company Home > Data Dictionary > Models 

Click On AddContent upload this xml file into Model , Don't forget to active you model (check out bottom presentation).

Add it to the UI by adding web-client-config-custom.xml and webclient.properties to
Company Home > Data Dictionary > Web Client Extension 

Go to Web Client Admin Console and type reload to reload the web client

Remember you need to update the following docs in Data Dictionary

  • custom-model.xml
  • web-client-config-custom.xml
  • webclient.properties

this article is collected from “http://www.optaros.com/ and http://knol.google.com/k/customize-alfresco# "

1 comment: