Content Modelling and Policy Behaviors0Jan VonkaRepository Team, Alfresco
Introduction - Contents1IntroductionModellingOverviewComponentsExamplesBehavioursOverviewComponentsExamplesPast, present & futureQ & A … feedback
Introduction – Hi2About meI’ve been with Alfresco since early 2007primarily working in the core repository teamworked for various companies in UK & CaliforniaI enjoy flying hot-air balloons ;-)Spellingto be consistent I’ll stick with the British spellingModelling <=> ModelingBehaviour <=> BehaviorAbout youModelling vs Behaviours … how much time (50/50) ?I’d like to allow enough time for Q & A and general feedback (your experience)
Introduction - Assumptions3How many of you have … ?attended training courseDevConJumpStart courseIntensive Developers courseand/or readProfessional Alfresco book (chapter 5)Jeff Pott’sAlfresco Developer Guide (chapters 3 & 4)Alfresco wiki (“Data Dictionary” and related pages)and/or hands-on experiencefollowed examples (eg. Books and/or Alfresco SDK)developed your own custom content model & app’
Introduction – “Dictionary” Definitions4[something] used as an example to follow or imitateto make [something] conform to a chosen standardModellingthe way in which [something] behaves in response to a particular situation or stimulusBehaviour
Introduction – Alfresco Content Repository5which enables storage of a potentially arbitrary network of entity datacontent entities “metadata” (about the entities)relationships (between the entities)Storesstore ref(erence)root nodeNodesunique node ref(erence)Propertieson nodes(Peer) Associationsfrom source to target nodeChild associationsbetween parent & child nodeprimary & secondaryDomainEmbeds a storage engine
Introduction – model / domain consistency6Model / domain consistency can be maintained via …Content Model + Integrity Checkerformal model definitionincluding built-in constraintsoption to also write & plug-in custom constraints (not specifically covered here)Behaviourscustom business logic bound to policiesRules & Actionsnot covered here … see separate session
Modelling7[something] used as an example to follow or imitateto make [something] conform to a chosen standard
Modelling overview – Content Models8Content modelsare all about metadata (data that describes data)constrain otherwise arbitrary nodes, properties and associationsare named and define one or more namespacescan import namespaces in order to allow references to other modelsmust be configured and loaded in dependent order“bootstrap” models are statically loaded from the filesystem (“extensions” classpath) when repo starts“dynamic” models are dynamically loaded from the repo (“Models” space) when models are added or changedintegrity checks fire when transaction commitsmandatory can be enforced (else node is marked as incomplete)
Modelling overview – Services9Get def’ (or all QNames)modeltypes / aspectpropertydatatypeconstraintassociationalso: is sub-class ?Also refers toQNameNamespaceService (prefix resolver)Dictionary ServiceNodescreate, move, delete, restorePropertiesset, get, removeAssociationscreate, remove, get sources, get targetsChild Associationsget children, get parentsget primary parentNode Service
Modelling overview - M2 (meta-)model10AspectTypeAssociationClassChild AssociationData TypePropertyConstraint
Modelling overview – M2 (meta-)model11modelSchema.xsdImportsNamespacesData-typesConstraintsTypes / AspectsPropertiesConstraintsAssociationsChild AssociationsSummary
Model components – Types & Aspects (Nodes)12Nodemust be of a given type when createdcan also setType (ie. specialise / change type)may have zero or more aspects attachedeither from type or at runtimemay have a set of properties defined by type & aspects (including inherited types & aspects)may be associated with other nodesdefined by type & aspects (including inherited types & aspects)
Model components – Properties13Propertymust be namedmust be of a given datatypemay be single-valued (default) or multi-valuedmay have zero or more constraints (inline or referenced)may be mandatoryeither: enforced or: relaxed (if missing, node marked with incomplete aspect)may have default valuemay be “residual”in this case there is no associated property definitioncan be overridden in terms of inheritanceto a limited extent – mandatory, default, constraints
Model components – Constraints14Built-in constraint types:LIST		(“ListOfValuesConstraint)LENGTH	(“StringLengthConstraint”)MINMAX	(“NumericRangeConstraint”)REGEXP	(“RegexConstraint”)Other examples, eg. RM caveats use:“RMListOfValuesConstraint” (extends “ListOfValuesConstraint”)You can hook in your own constraint implementationsimplement “Constraint” interfacetypically extend “AbstractConstraint”must have default constructor (as it’s used to instantiate it)in model, define constraint with “type” attribute set to fully-qualified class namemake sure you unit test your constraint (it is performance sensitive)Constraints executeas part of integrity checks prior to commit (ie. at the end of a server transaction)
Model components – Associations (Peer)15(Peer) Associationassociation type is namedsource node may be associated with zero or more target nodesmay be mandatoryenforced or relaxed (missing => node marked with incomplete aspect)cardinality can be defined via many / mandatory0 or 1(mandatory = false, many = false)1 (mandatory = true, many = false)0 or more (mandatory = false, many = true)1 or more (mandatory = true, many = true)
Model components – Child Associations16Child Associationdefined in same way as peer association with extra featuresparent node may be associated with zero or more child nodesaffects certain operations, eg. delete will cascadealso defines if child name can be duplicated or unique within parenta node can have one primary child associationa node may have one or more secondary child associations
Model components – Admin Node Browser17Don’t forget “the Node Browser is your friend !”in theory never lies …… although be careful with browser back button (JSF issue)
Model components – some changes since 3.x18Dynamic modelssince 3.0reduces need for server restart, also enables multi-tenancy optionCMIS mappingCMIS type, CMIS property, CMIS relationship (peer assoc)CMIS document (cm:content), CMIS folder (cm:folder)Constraints support title & description (needed by RM)since 3.2Tightened validation check for content modelssince 3.4unfortunately, due to a long standing bug, it has always been possible to define new model elements using a namespace that wasn't defined by the containing model (eg. using an imported namespace)with the recent bug fix, it is now only possible to create model elements whose namespace is also defined by the containing model“DataModel” split out from “Repository”since 3.4split into separate JAR / Eclipse project – for future SOLR integration
Model components – example19sys:referenceablesys:store-protocol
sys:store-identifier
sys:node-uuid
sys:node-dbidsys:basecm:auditablecm:created
cm:creator
cm:modified
cm:modifiercm:cmobject- cm:namecm:foldercm:content
Example – custom model20cm:foldercm:contentmy:customBaseFoldermy:customBaseAspectmy:customBaseContentmy:customContentmy:customSubFoldermy:customSubAspect
Model demo – Sample XMI generator21… more here …Map<String, Object> fmModel = new HashMap<String, Object>();fmModel.put("prefixDelimiter", prefixDelimiter);fmModel.put("classes", allM2Classes);fmModel.put("datatypes", datatypes);Configuration cfg = new Configuration();cfg.setObjectWrapper(ObjectWrapper.DEFAULT_WRAPPER);String userDir = System.getProperty("user.dir");cfg.setDirectoryForTemplateLoading(newFile(userDir+"/source/test-resources/SimpleXMI"));// UML 1.4 / XMI 1.2 - suitable for ArgoUML (eg. 0.30.2)Template temp = cfg.getTemplate("simple-Xmi1.2-Uml1.4.ftl");File f = new File(userDir, "simpleXMI-"+System.currentTimeMillis()+".xmi");Writer out = new FileWriter(f);temp.process(fmModel, out);out.flush();out.close();… more here …GenSimpleXMIFromModel.java (extract)… more here …<#list datatypesas datatype>           <#assign split=datatype.name?index_of(":")>           <UML:DataTypexmi.id = 'id-datatype:${datatype.name}' name = '${datatype.name?substring(split+1)}'isSpecification= 'false' isRoot = 'false' isLeaf = 'false'isAbstract= 'false'/> </#list> <#list classes as class>      <UML:Classxmi.id = 'id-class:${class.name}' 	name = '${class.name?replace(":",prefixDelimiter)}’     	isSpecification= 'false' isRoot = 'false'isLeaf= 'false' isAbstract = 'false' isActive = 'false'>          <#if class.isAspect() == true >		<UML:ModelElement.stereotype> 	<UML:Stereotypexmi.idref = 'id-stereotype:aspect'/> 	</UML:ModelElement.stereotype>	    <#else>… more here …simple-Xmi1.2-Uml1.4.ftl (extract)
Model examples –DevCon sample22
Model examples – Web Quick Start (WQS)23
Model examples – many “OOTB”24Many examples “out-of-the-box”Search for “*Model.xml” across the Alfresco source treeCore model files (with defined namespaces) include:dictionaryModel.xmlhttp://www.alfresco.org (alf)http://www.alfresco.org/model/dictionary/1.0 (d)http://www.alfresco.org/view/repository/1.0 (view)systemModel.xmlhttp://www.alfresco.org/model/system/1.0 (sys)http://www.alfresco.org/system/registry/1.0 (reg)http://www.alfresco.org/system/modules/1.0 (module)contentModel.xmlhttp://www.alfresco.org/model/content/1.0 (cm)http://www.alfresco.org/model/rendition/1.0 (rn)http://www.alfresco.org/model/exif/1.0 (exif)
Model examples – modules (eg. RM, WQS)25Alfresco modules also provide some great examples, eg.Records Management (RM / DOD5015)dod5015Model.xmlhttp://www.alfresco.org/model/dod5015/1.0 (dod)recordsCustomModel.xml (dynamically managed)http://www.alfresco.org/model/rmcustom/1.0 (rmc)Web Quick Start (WQS)webSiteModel.xmlhttp://www.alfresco.org/model/website/1.0 (ws)
Behaviours26the way in which [something] behaves in response to a particular situation or stimulus
Behaviours overview – policy + behaviour 	27Policies provide hook points to which you can bind behaviours to events based on class or associationbehaviours are (policy) handlers that execute specific business logicbehaviours can be implemented in Java and/or JavaScriptBehaviours can be bound to a type or aspectnode in the content repository must be of a single typenode may have one or more aspects attachedaspects are either inherited from its type (defined by the model)or can be attached (or detached) at runtime …allowing a node to dynamically inherit features and capabilitiesaspects can be interpreted by the repository to change behavioureg. by the presence of an aspect (even with no properties)
Behaviours overview – policy component	28From JavaDoc (org.alfresco.repo.policy) …The Policy Component manages Policies and Behaviours. It provides theability to:a) Register policiesb) Bind behaviours to policiesc) Invoke policy behavioursA behaviour may be bound to a Policy before the Policy is registered. Inthis case, the behaviour is not validated (i.e. checked to determine if itSupports the policy interface) until the Policy is registered. Otherwise,the behaviour is validated at bind-time.Policies may be selectively "turned off" by the Behaviour Filter.
Behaviour components – behaviour interface29BehaviourBaseBehaviourJavaBehaviourScriptBehaviour
Behaviour components – policy interface30  PolicyClassPolicy (type or aspect)AssociationPolicy (peer or parent-child)PropertyPolicy (not used)
Behaviour components – some OOTB policies31Search for “*Policies.java” across the Alfresco source treeExamples include:NodeServicePoliciesbefore/onCreateNode, beforeDeleteNode (don’t use “on”)before/onUpdateNodeonUpdatePropertiesbefore/onAddAspectbefore/onRemoveAspectbefore/onCreateChildAssociationbefore/onDeleteChildAssocationonCreateAssociationonDeleteAssociation….ContentServicePoliciesonContentUpdateonContentPropertyUpdate
Behaviour components - other policy examples32CopyServicePoliciesbefore/onCopyonCopyCompleteCheckOutCheckInServicePoliciesbefore/OnCheckOutbefore/OnCheckInbefore/OnCancelCheckOutAnd more …VersionServicePoliciesStoreSelectorPoliciesAsynchronousActionExecutionQueuePoliciesRecordsManagementPoliciesNote: you can define, register and invoke you own custom policies, eg.RecordsManagementPolicies <= RecordsManagementActionServiceImpl
Behaviour components – register & invoke33public interface NodeServicePolicies{		public interface OnAddAspectPolicy extends ClassPolicy	{		public static final QName QNAME = QName.createQName(NamespaceService.ALFRESCO_URI, "onAddAspect");		// Called after an <b>aspect</b> has been added to a node		public void onAddAspect(NodeRefnodeRef, QNameaspectTypeQName);	}}public abstract class AbstractNodeServiceImpl implements NodeService{	// note: policyComponent is injected … (not shown here)	public void init()	{		// Register the policyonAddAspectDelegate = policyComponent.registerClassPolicy									(NodeServicePolicies.OnAddAspectPolicy.class);	} 	protected void invokeOnAddAspect(NodeRefnodeRef, QNameaspectTypeQName)	{		NodeServicePolicies.OnAddAspectPolicy policy = onAddAspectDelegate.get(nodeRef, aspectTypeQName);policy.onAddAspect(nodeRef, aspectTypeQName);	}}
Behaviour components – bind & implement34public class XyzAspect implements NodeServicePolicies.OnAddAspectPolicy, ...{	// note: policyComponent is injected … (not shown here)	public void init()	{		// bind to the policypolicyComponent.bindClassBehaviour(OnAddAspectPolicy.QNAME,ContentModel.ASPECT_XYZ,			new JavaBehaviour(this, "onAddAspect”, 							   Behaviour.NotificationFrequency.TRANSACTION_COMMIT));	}	public void onAddAspect(NodeRefnodeRef, QNameaspectTypeQName)	{		// implement behaviour here … (for when aspect XYZ is added)	}}
Behaviour components – class vs service binding35…//// note: usually try to bind on specific class (type/aspect) rather than service method//// class binding – specific type or aspectpolicyComponent.bindClassBehaviour(NodeServicePolicies.OnUpdatePropertiesPolicy.QNAME,ContentModel.TYPE_PERSON, 		new JavaBehaviour(this, 						"onUpdateProperties”,Behaviour.NotificationFrequency.EVERY_EVENT));// service binding – all types/aspectspolicyComponent.bindClassBehaviour(            NodeServicePolicies.OnUpdatePropertiesPolicy.QNAME,this,		new JavaBehaviour(this, 						 "onUpdateProperties”,Behaviour.NotificationFrequency.EVERY_EVENT));…
Behaviour components - handle now or later36Notification Frequencybehaviours can be defined with a notification frequency – “every event” (default), “first event”, “transaction commit”consider that during a given transaction, certain policies may fire multiple times (ie. “every event”)can set notification frequency to “first event” or “transaction commit”Using Transactional Resourceoption to execute logic immediately or queue (eg. via transactional resource) until commit (beforeCommit and/or afterCommit)AlfrescoTransactionSupport.bindResource(K, V)V = AlfrescoTransactionSupport.getResource(K)
Behaviour components – disable / (re-)enable37Behaviours can be temporarily disabledBehaviourFilterinterfacefor current transaction onlyfor “class” (type or aspect) or “node + class”disableBehaviourenableBehaviourisEnabledfor “node”enableBehavioursfor “all”disableAllBehavioursenableAllBehavioursisActivatedBehaviour interfacefor current thread onlydisable / enable, eg. in try / finally blockExamples – importer, transfer – disable behaviours
Behaviour components - delete is delete !38From the perspective of the custom behaviourdelete is delete (you should not need to care whether it is archived)create is create (even if it is restored from the archive)Bind to beforeDeleteNode (not onDeleteNode)note: will fire for parent and recursively for each of it’s cascade deleted children (if any)Don’t rely (or be dependent) on the archive storedeleted node may not be archivedarchived node may never be restoredyou should not need to check for archive storeOne exception is peer associationsassocs to “archived” nodes may remain (pending ALF-4119 for 3.4+)
Behaviour components - delete is delete ! (cont)39“live” store“archive” storedeleteNode(purgeArchivedNode)deleteNoderestoreNodearchive://SpacesStoreversion://version2Storeworkspace://SpacesStoredeleteNode“version” storecreateVersiondeleteVersiondeleteVersionHistory
Behaviour components – some changes in 3.x40More than one handler can be registered for a given policysince 3.0We now also trigger policies through the type hierarchysince 3.4if you use earlier Alfresco and yet to upgrade then workaround is to bind to service bind and use “isSubClassOf” to check typeYou should not need to check for archive storesince 3.3operations on archive store no longer fire policesalso applies to version store
Example behaviours - more41Search through the code for policy bindings or use Eclipse to find call hierarchy forbindClassBehaviour (x2)bindAssociationBehaviour (x3)Many examples both in core services as well as module extensions such asWeb Quick Starthttp://wiki.alfresco.com/wiki/Web_Quick_Start_Developer_Guide#BehavioursDOD 5015 (Records Management)You can refer to the SDK for a simple exampleAlso, for JavaScript Behaviours, refer to *old* RM module
Modelling & Behaviours – some general tips42Modellingconsider using dynamic models during dev & test cyclesbeware of deep class hierarchiesconsider performance of any custom registered constraintsBehavioursconsider notification frequencyadd debug loggingdon’t rely on archive storecan temporarily disable/re-enable (thread or transaction)Generalstart with the SDK and if needed move to complete SVN source treewrite unit tests (+ve & -ve) to exercise custom models & behavioursrun existing regression tests (eg. “ant test-repository” or continuous)develop and package as an AMP (Alfresco Module Package)

Content Modeling Behavior

  • 1.
    Content Modelling andPolicy Behaviors0Jan VonkaRepository Team, Alfresco
  • 2.
  • 3.
    Introduction – Hi2AboutmeI’ve been with Alfresco since early 2007primarily working in the core repository teamworked for various companies in UK & CaliforniaI enjoy flying hot-air balloons ;-)Spellingto be consistent I’ll stick with the British spellingModelling <=> ModelingBehaviour <=> BehaviorAbout youModelling vs Behaviours … how much time (50/50) ?I’d like to allow enough time for Q & A and general feedback (your experience)
  • 4.
    Introduction - Assumptions3Howmany of you have … ?attended training courseDevConJumpStart courseIntensive Developers courseand/or readProfessional Alfresco book (chapter 5)Jeff Pott’sAlfresco Developer Guide (chapters 3 & 4)Alfresco wiki (“Data Dictionary” and related pages)and/or hands-on experiencefollowed examples (eg. Books and/or Alfresco SDK)developed your own custom content model & app’
  • 5.
    Introduction – “Dictionary”Definitions4[something] used as an example to follow or imitateto make [something] conform to a chosen standardModellingthe way in which [something] behaves in response to a particular situation or stimulusBehaviour
  • 6.
    Introduction – AlfrescoContent Repository5which enables storage of a potentially arbitrary network of entity datacontent entities “metadata” (about the entities)relationships (between the entities)Storesstore ref(erence)root nodeNodesunique node ref(erence)Propertieson nodes(Peer) Associationsfrom source to target nodeChild associationsbetween parent & child nodeprimary & secondaryDomainEmbeds a storage engine
  • 7.
    Introduction – model/ domain consistency6Model / domain consistency can be maintained via …Content Model + Integrity Checkerformal model definitionincluding built-in constraintsoption to also write & plug-in custom constraints (not specifically covered here)Behaviourscustom business logic bound to policiesRules & Actionsnot covered here … see separate session
  • 8.
    Modelling7[something] used asan example to follow or imitateto make [something] conform to a chosen standard
  • 9.
    Modelling overview –Content Models8Content modelsare all about metadata (data that describes data)constrain otherwise arbitrary nodes, properties and associationsare named and define one or more namespacescan import namespaces in order to allow references to other modelsmust be configured and loaded in dependent order“bootstrap” models are statically loaded from the filesystem (“extensions” classpath) when repo starts“dynamic” models are dynamically loaded from the repo (“Models” space) when models are added or changedintegrity checks fire when transaction commitsmandatory can be enforced (else node is marked as incomplete)
  • 10.
    Modelling overview –Services9Get def’ (or all QNames)modeltypes / aspectpropertydatatypeconstraintassociationalso: is sub-class ?Also refers toQNameNamespaceService (prefix resolver)Dictionary ServiceNodescreate, move, delete, restorePropertiesset, get, removeAssociationscreate, remove, get sources, get targetsChild Associationsget children, get parentsget primary parentNode Service
  • 11.
    Modelling overview -M2 (meta-)model10AspectTypeAssociationClassChild AssociationData TypePropertyConstraint
  • 12.
    Modelling overview –M2 (meta-)model11modelSchema.xsdImportsNamespacesData-typesConstraintsTypes / AspectsPropertiesConstraintsAssociationsChild AssociationsSummary
  • 13.
    Model components –Types & Aspects (Nodes)12Nodemust be of a given type when createdcan also setType (ie. specialise / change type)may have zero or more aspects attachedeither from type or at runtimemay have a set of properties defined by type & aspects (including inherited types & aspects)may be associated with other nodesdefined by type & aspects (including inherited types & aspects)
  • 14.
    Model components –Properties13Propertymust be namedmust be of a given datatypemay be single-valued (default) or multi-valuedmay have zero or more constraints (inline or referenced)may be mandatoryeither: enforced or: relaxed (if missing, node marked with incomplete aspect)may have default valuemay be “residual”in this case there is no associated property definitioncan be overridden in terms of inheritanceto a limited extent – mandatory, default, constraints
  • 15.
    Model components –Constraints14Built-in constraint types:LIST (“ListOfValuesConstraint)LENGTH (“StringLengthConstraint”)MINMAX (“NumericRangeConstraint”)REGEXP (“RegexConstraint”)Other examples, eg. RM caveats use:“RMListOfValuesConstraint” (extends “ListOfValuesConstraint”)You can hook in your own constraint implementationsimplement “Constraint” interfacetypically extend “AbstractConstraint”must have default constructor (as it’s used to instantiate it)in model, define constraint with “type” attribute set to fully-qualified class namemake sure you unit test your constraint (it is performance sensitive)Constraints executeas part of integrity checks prior to commit (ie. at the end of a server transaction)
  • 16.
    Model components –Associations (Peer)15(Peer) Associationassociation type is namedsource node may be associated with zero or more target nodesmay be mandatoryenforced or relaxed (missing => node marked with incomplete aspect)cardinality can be defined via many / mandatory0 or 1(mandatory = false, many = false)1 (mandatory = true, many = false)0 or more (mandatory = false, many = true)1 or more (mandatory = true, many = true)
  • 17.
    Model components –Child Associations16Child Associationdefined in same way as peer association with extra featuresparent node may be associated with zero or more child nodesaffects certain operations, eg. delete will cascadealso defines if child name can be duplicated or unique within parenta node can have one primary child associationa node may have one or more secondary child associations
  • 18.
    Model components –Admin Node Browser17Don’t forget “the Node Browser is your friend !”in theory never lies …… although be careful with browser back button (JSF issue)
  • 19.
    Model components –some changes since 3.x18Dynamic modelssince 3.0reduces need for server restart, also enables multi-tenancy optionCMIS mappingCMIS type, CMIS property, CMIS relationship (peer assoc)CMIS document (cm:content), CMIS folder (cm:folder)Constraints support title & description (needed by RM)since 3.2Tightened validation check for content modelssince 3.4unfortunately, due to a long standing bug, it has always been possible to define new model elements using a namespace that wasn't defined by the containing model (eg. using an imported namespace)with the recent bug fix, it is now only possible to create model elements whose namespace is also defined by the containing model“DataModel” split out from “Repository”since 3.4split into separate JAR / Eclipse project – for future SOLR integration
  • 20.
    Model components –example19sys:referenceablesys:store-protocol
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
    Example – custommodel20cm:foldercm:contentmy:customBaseFoldermy:customBaseAspectmy:customBaseContentmy:customContentmy:customSubFoldermy:customSubAspect
  • 28.
    Model demo –Sample XMI generator21… more here …Map<String, Object> fmModel = new HashMap<String, Object>();fmModel.put("prefixDelimiter", prefixDelimiter);fmModel.put("classes", allM2Classes);fmModel.put("datatypes", datatypes);Configuration cfg = new Configuration();cfg.setObjectWrapper(ObjectWrapper.DEFAULT_WRAPPER);String userDir = System.getProperty("user.dir");cfg.setDirectoryForTemplateLoading(newFile(userDir+"/source/test-resources/SimpleXMI"));// UML 1.4 / XMI 1.2 - suitable for ArgoUML (eg. 0.30.2)Template temp = cfg.getTemplate("simple-Xmi1.2-Uml1.4.ftl");File f = new File(userDir, "simpleXMI-"+System.currentTimeMillis()+".xmi");Writer out = new FileWriter(f);temp.process(fmModel, out);out.flush();out.close();… more here …GenSimpleXMIFromModel.java (extract)… more here …<#list datatypesas datatype> <#assign split=datatype.name?index_of(":")> <UML:DataTypexmi.id = 'id-datatype:${datatype.name}' name = '${datatype.name?substring(split+1)}'isSpecification= 'false' isRoot = 'false' isLeaf = 'false'isAbstract= 'false'/> </#list> <#list classes as class> <UML:Classxmi.id = 'id-class:${class.name}' name = '${class.name?replace(":",prefixDelimiter)}’ isSpecification= 'false' isRoot = 'false'isLeaf= 'false' isAbstract = 'false' isActive = 'false'> <#if class.isAspect() == true > <UML:ModelElement.stereotype> <UML:Stereotypexmi.idref = 'id-stereotype:aspect'/> </UML:ModelElement.stereotype> <#else>… more here …simple-Xmi1.2-Uml1.4.ftl (extract)
  • 29.
  • 30.
    Model examples –Web Quick Start (WQS)23
  • 31.
    Model examples –many “OOTB”24Many examples “out-of-the-box”Search for “*Model.xml” across the Alfresco source treeCore model files (with defined namespaces) include:dictionaryModel.xmlhttp://www.alfresco.org (alf)http://www.alfresco.org/model/dictionary/1.0 (d)http://www.alfresco.org/view/repository/1.0 (view)systemModel.xmlhttp://www.alfresco.org/model/system/1.0 (sys)http://www.alfresco.org/system/registry/1.0 (reg)http://www.alfresco.org/system/modules/1.0 (module)contentModel.xmlhttp://www.alfresco.org/model/content/1.0 (cm)http://www.alfresco.org/model/rendition/1.0 (rn)http://www.alfresco.org/model/exif/1.0 (exif)
  • 32.
    Model examples –modules (eg. RM, WQS)25Alfresco modules also provide some great examples, eg.Records Management (RM / DOD5015)dod5015Model.xmlhttp://www.alfresco.org/model/dod5015/1.0 (dod)recordsCustomModel.xml (dynamically managed)http://www.alfresco.org/model/rmcustom/1.0 (rmc)Web Quick Start (WQS)webSiteModel.xmlhttp://www.alfresco.org/model/website/1.0 (ws)
  • 33.
    Behaviours26the way inwhich [something] behaves in response to a particular situation or stimulus
  • 34.
    Behaviours overview –policy + behaviour 27Policies provide hook points to which you can bind behaviours to events based on class or associationbehaviours are (policy) handlers that execute specific business logicbehaviours can be implemented in Java and/or JavaScriptBehaviours can be bound to a type or aspectnode in the content repository must be of a single typenode may have one or more aspects attachedaspects are either inherited from its type (defined by the model)or can be attached (or detached) at runtime …allowing a node to dynamically inherit features and capabilitiesaspects can be interpreted by the repository to change behavioureg. by the presence of an aspect (even with no properties)
  • 35.
    Behaviours overview –policy component 28From JavaDoc (org.alfresco.repo.policy) …The Policy Component manages Policies and Behaviours. It provides theability to:a) Register policiesb) Bind behaviours to policiesc) Invoke policy behavioursA behaviour may be bound to a Policy before the Policy is registered. Inthis case, the behaviour is not validated (i.e. checked to determine if itSupports the policy interface) until the Policy is registered. Otherwise,the behaviour is validated at bind-time.Policies may be selectively "turned off" by the Behaviour Filter.
  • 36.
    Behaviour components –behaviour interface29BehaviourBaseBehaviourJavaBehaviourScriptBehaviour
  • 37.
    Behaviour components –policy interface30 PolicyClassPolicy (type or aspect)AssociationPolicy (peer or parent-child)PropertyPolicy (not used)
  • 38.
    Behaviour components –some OOTB policies31Search for “*Policies.java” across the Alfresco source treeExamples include:NodeServicePoliciesbefore/onCreateNode, beforeDeleteNode (don’t use “on”)before/onUpdateNodeonUpdatePropertiesbefore/onAddAspectbefore/onRemoveAspectbefore/onCreateChildAssociationbefore/onDeleteChildAssocationonCreateAssociationonDeleteAssociation….ContentServicePoliciesonContentUpdateonContentPropertyUpdate
  • 39.
    Behaviour components -other policy examples32CopyServicePoliciesbefore/onCopyonCopyCompleteCheckOutCheckInServicePoliciesbefore/OnCheckOutbefore/OnCheckInbefore/OnCancelCheckOutAnd more …VersionServicePoliciesStoreSelectorPoliciesAsynchronousActionExecutionQueuePoliciesRecordsManagementPoliciesNote: you can define, register and invoke you own custom policies, eg.RecordsManagementPolicies <= RecordsManagementActionServiceImpl
  • 40.
    Behaviour components –register & invoke33public interface NodeServicePolicies{ public interface OnAddAspectPolicy extends ClassPolicy { public static final QName QNAME = QName.createQName(NamespaceService.ALFRESCO_URI, "onAddAspect"); // Called after an <b>aspect</b> has been added to a node public void onAddAspect(NodeRefnodeRef, QNameaspectTypeQName); }}public abstract class AbstractNodeServiceImpl implements NodeService{ // note: policyComponent is injected … (not shown here) public void init() { // Register the policyonAddAspectDelegate = policyComponent.registerClassPolicy (NodeServicePolicies.OnAddAspectPolicy.class); } protected void invokeOnAddAspect(NodeRefnodeRef, QNameaspectTypeQName) { NodeServicePolicies.OnAddAspectPolicy policy = onAddAspectDelegate.get(nodeRef, aspectTypeQName);policy.onAddAspect(nodeRef, aspectTypeQName); }}
  • 41.
    Behaviour components –bind & implement34public class XyzAspect implements NodeServicePolicies.OnAddAspectPolicy, ...{ // note: policyComponent is injected … (not shown here) public void init() { // bind to the policypolicyComponent.bindClassBehaviour(OnAddAspectPolicy.QNAME,ContentModel.ASPECT_XYZ, new JavaBehaviour(this, "onAddAspect”, Behaviour.NotificationFrequency.TRANSACTION_COMMIT)); } public void onAddAspect(NodeRefnodeRef, QNameaspectTypeQName) { // implement behaviour here … (for when aspect XYZ is added) }}
  • 42.
    Behaviour components –class vs service binding35…//// note: usually try to bind on specific class (type/aspect) rather than service method//// class binding – specific type or aspectpolicyComponent.bindClassBehaviour(NodeServicePolicies.OnUpdatePropertiesPolicy.QNAME,ContentModel.TYPE_PERSON, new JavaBehaviour(this, "onUpdateProperties”,Behaviour.NotificationFrequency.EVERY_EVENT));// service binding – all types/aspectspolicyComponent.bindClassBehaviour( NodeServicePolicies.OnUpdatePropertiesPolicy.QNAME,this, new JavaBehaviour(this, "onUpdateProperties”,Behaviour.NotificationFrequency.EVERY_EVENT));…
  • 43.
    Behaviour components -handle now or later36Notification Frequencybehaviours can be defined with a notification frequency – “every event” (default), “first event”, “transaction commit”consider that during a given transaction, certain policies may fire multiple times (ie. “every event”)can set notification frequency to “first event” or “transaction commit”Using Transactional Resourceoption to execute logic immediately or queue (eg. via transactional resource) until commit (beforeCommit and/or afterCommit)AlfrescoTransactionSupport.bindResource(K, V)V = AlfrescoTransactionSupport.getResource(K)
  • 44.
    Behaviour components –disable / (re-)enable37Behaviours can be temporarily disabledBehaviourFilterinterfacefor current transaction onlyfor “class” (type or aspect) or “node + class”disableBehaviourenableBehaviourisEnabledfor “node”enableBehavioursfor “all”disableAllBehavioursenableAllBehavioursisActivatedBehaviour interfacefor current thread onlydisable / enable, eg. in try / finally blockExamples – importer, transfer – disable behaviours
  • 45.
    Behaviour components -delete is delete !38From the perspective of the custom behaviourdelete is delete (you should not need to care whether it is archived)create is create (even if it is restored from the archive)Bind to beforeDeleteNode (not onDeleteNode)note: will fire for parent and recursively for each of it’s cascade deleted children (if any)Don’t rely (or be dependent) on the archive storedeleted node may not be archivedarchived node may never be restoredyou should not need to check for archive storeOne exception is peer associationsassocs to “archived” nodes may remain (pending ALF-4119 for 3.4+)
  • 46.
    Behaviour components -delete is delete ! (cont)39“live” store“archive” storedeleteNode(purgeArchivedNode)deleteNoderestoreNodearchive://SpacesStoreversion://version2Storeworkspace://SpacesStoredeleteNode“version” storecreateVersiondeleteVersiondeleteVersionHistory
  • 47.
    Behaviour components –some changes in 3.x40More than one handler can be registered for a given policysince 3.0We now also trigger policies through the type hierarchysince 3.4if you use earlier Alfresco and yet to upgrade then workaround is to bind to service bind and use “isSubClassOf” to check typeYou should not need to check for archive storesince 3.3operations on archive store no longer fire policesalso applies to version store
  • 48.
    Example behaviours -more41Search through the code for policy bindings or use Eclipse to find call hierarchy forbindClassBehaviour (x2)bindAssociationBehaviour (x3)Many examples both in core services as well as module extensions such asWeb Quick Starthttp://wiki.alfresco.com/wiki/Web_Quick_Start_Developer_Guide#BehavioursDOD 5015 (Records Management)You can refer to the SDK for a simple exampleAlso, for JavaScript Behaviours, refer to *old* RM module
  • 49.
    Modelling & Behaviours– some general tips42Modellingconsider using dynamic models during dev & test cyclesbeware of deep class hierarchiesconsider performance of any custom registered constraintsBehavioursconsider notification frequencyadd debug loggingdon’t rely on archive storecan temporarily disable/re-enable (thread or transaction)Generalstart with the SDK and if needed move to complete SVN source treewrite unit tests (+ve & -ve) to exercise custom models & behavioursrun existing regression tests (eg. “ant test-repository” or continuous)develop and package as an AMP (Alfresco Module Package)

Editor's Notes

  • #10 Other foundation services include Content Service, Search Service …Other higher-level services include FileFolderService, CheckoutCheckInService, VersionService, CopyService …
  • #19 ALF-680 - Previously valid content models now fail with CMISAbstractDictionaryService$DictionaryRegistry exception (r20488)CHK-8823 -Dictionary/Constraint improvements (required by MOB-1276) (r15913)
  • #39 ALF-955 - Deletion of dynamic custom model (Ent 3.2.1 / Com 3.3)ALF-4119 - NodeService: beforeDeleteNode archiving (WIP – targeted for Com 3.4b)
  • #41 ALF-3885 - Allow multiple policies through type hierarchy (r21253) (Com 3.4.a / Ent 3.4.0)CHK-2720 - Fixed AR-401 Can only have one policy handler (r8698)