cancel
Showing results for 
Search instead for 
Did you mean: 
resplin
Elite Collaborator
Elite Collaborator

Obsolete Pages{{Obsolete}}

The official documentation is at: http://docs.alfresco.com



Content Modeling
For many content models, it is useful to have some data populated when the model is loaded.  This is done by bootstrapping some data.  One good example is in the Records Management module. 

Importing the data in an import XML file or an ACP file as part of your modules initialization can be easily done.


  1. First place your ACP or XML file somewhere in your module's class path.  Often this will be in the config folder structure.
  2. Next add the following config to your module-context.xml file, specifying either the XML or ACP file by its location on the classpath.


<bean id='myModule.bootstrap'
      class='org.alfresco.repo.module.ImporterModuleComponent'
      parent='module.baseComponent'>
  
   <property name='moduleId' value='myModule' />
   <property name='name' value='myModuleBootstrap' />
   <property name='description' value='My Modules initial data requirements' />
   <property name='sinceVersion' value='1.0' />
   <property name='appliesFromVersion' value='1.0' />
  
   <property name='importer' ref='spacesBootstrap'/>
   <property name='bootstrapViews'>
      <list>
         <props>
            <prop key='path'>/${spaces.company_home.childname}</prop>
            <prop key='location'>alfresco/module/myModule-123/myACP.acp</prop>
         </props>
      </list>
   </property>

</bean>


Property Values


  • moduleId = the id of the module that this import component relates to.
  • name = the name of the import component.
  • description = a description of the import component.
  • sinceVersion = the version of the module this import component was introduced.
  • appliesFromVersion = the version of the module from which this import component applies from.
  • importer = the importer to use when importing the data

BootstrapViews

A list of the ACP or XML files to be imported and the location in the destination repository where the data should be imported.




Procedure for Adding Bootstrapped Files


Where you put them in the amp structure does not matter at all. What does matter is how you bootstrap it. Bootstrap code allows you to refer to an XML file that points to how nodes are supposed to be added. 

You can add your information in one of two ways - in an XML file that points to files explicitly, or an ACP file (which also has an XML file that points to file, it's just easier to generate it through space export).

The easiest way to do this is: 

  1. Put your webscripts into the appropriate directory in data dictionary.  
  2. Delete ALL webscripts OTHER than yours. 
  3. Do an export of the contents of the directory. This will create an ACP file.  Download the ACP file to your desktop and copy it to one of the module directories (e.g. bootstrap).
  4. Create bootstrap-context.xml in context subdirectory of your module, i.e. config\alfresco\module\org.alfresco.module.yourmodule\context\
  5.  In the file, add a bean for bootstrapping, and point it to the ACP file: 



    <bean id='org_alfresco_module_bootstrapSpaces' class='org.alfresco.repo.module.ImporterModuleComponent' parent='module.baseComponent'>
        <property name='moduleId' value='org.alfresco.module.yourmodule.project' />
        <property name='name' value='org.alfresco.module.yourmodule.bootstrapSpaces' />
        <property name='description' value='Initial data requirements' />
        <property name='sinceVersion' value='0.4' />
        <property name='appliesFromVersion' value='0.4' />

        <property name='importer' ref='spacesBootstrap'/>
        <property name='bootstrapViews'>
            <list>
                <props>
                    <prop key='path'>/cm:categoryRoot/cm:generalclassifiable</prop>
                    <prop key='location'>alfresco/module/org.alfresco.module.yourmodule/bootstrap/rm_categories.xml</prop>
     </props>
            <props>
<props>
                     <prop key='path'>/${spaces.company_home.childname}/${spaces.dictionary.childname}/cm:webscripts</prop>
                     <prop key='location'>alfresco/bootstrap/web_scripts.acp</prop>
                 </props>
            </list>
        </property>
    </bean>

In the snippet above, web_scripts.acp should get exploded to Web Scripts directory: since alfresco parses xpath expressions the correct path to the Web Scripts folder is /cm:webscripts. It's always possible to derive the correct XPath expression of an alfresco content by using the 'Node Browser'. 

After that, you can start testing.  The bootstrap happens when you startup the first time after installing that AMP.  There is no good way to uninstall AMP right now, so for testing purposes, you can delete your db and file store, and recreate it from scratch.  There might be a better way, don't know.


Bootstrapping Categories via xml


Remember that your rm_categories.xml must contain only cm:generalclassifiable categories.
An example of the XML file is provided below:



<view:view xmlns:view='http://www.alfresco.org/view/repository/1.0'
           xmlns:sys='http://www.alfresco.org/model/system/1.0'
           xmlns:cm='http://www.alfresco.org/model/content/1.0'>

   <cm:category>
      <cm:name>Your Root Category</cm:name>
      <cm:subcategories>
         <cm:category>
            <cm:name>Your Parent Category</cm:name>
            <cm:subcategories>
               <cm:category>
                  <cm:name>Your Child Category</cm:name>
               </cm:category>
            </cm:subcategories>
         </cm:category>
      </cm:subcategories>
   </cm:category>

</view:view>

Bootstrapping Files/Spaces via xml


An alternative to the acp import is pointing to files explicitely via xml.



<bean id='customSpacesBootstrap' parent='spacesStoreImporter' singleton='true' >
   <property name='useExistingStore'>
       <value>${yourmodule.bootstrap.data}</value>
   </property>
   <property name='bootstrapViews'>
      <list>
          <props>
              <prop key='path'>/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.templates.email.childname}</prop>
               <prop key='location'>alfresco/module/yourmodule/bootstrap/config_email_templates.xml</prop>
           </props>
      </list>
   </property>
</bean>

In the snippet above, config_email_templates.xml contains the actual file references, as well as all file/folder properties. All predetermined files/folders will be placed in the 'Company Home/Data Dictionary/Email Templates' space.

Property Values


  • useExistingStore = if false the content won't be imported if the store exists
  • bootstrapViews = what you want to import and where it comes from

A good trick is to use a global property value for the 'useExistingStore' to turn bootstrapping on alfresco startup on or off.
If the store does not yet exist (the very first time a new alfresco installation starts up), the data will aways be bootstrapped, no matter the value, but from that moment on the store exists, and setting this to false means the next alfresco reboot these files won't be overridden with those on the classpath. Set it to true again and the next reboot the classpath files are loaded! Only import when YOU want it!



(!) XML imports can only replace/update/delete files that have their UUID set. (See #Import Strategy)

If you wish to bootstrap data to other stores or see all the available options, check out the import-export-context.xml

Back to the config_email_templates.xml, what would that look like?



<view:view xmlns:view='http://www.alfresco.org/view/repository/1.0'
    xmlns:cm='http://www.alfresco.org/model/content/1.0' xmlns:app='http://www.alfresco.org/model/application/1.0'
    xmlns:emailserver='http://www.alfresco.org/model/emailserver/1.0'>

<cm:folder view:childName='cm:My First Folder'>
        <app:uifacets />
        <cm:name>My First Folder</cm:name>
        <app:icon>space-icon-default</app:icon>
        <cm:title>My First Folder</cm:title>
        <cm:description></cm:description>
        <cm:contains>
            <cm:content view:childName='cm:custom_email_template.ftl'>
                <view:aspects>
                    <cm:titled />
                    <cm:author />
                    <app:inlineeditable />
                </view:aspects>
                <view:properties>
                    <app:editInline>true</app:editInline>
                    <cm:description>This is a custom email template.</cm:description>
                    <cm:content>contentUrl=classpath:alfresco/module/yourmodule/bootstrap/custom_email_template.ftl|mimetype=text/plain|size=|encoding=UTF-8|locale=en_US_</cm:content>
                    <cm:title>My first email template</cm:title>
                    <cm:author>Me</cm:author>
                    <cm:name>custom_email_template.ftl</cm:name>
                </view:properties>
                <view:associations></view:associations>
            </cm:content>
        </cm:contains>
    </cm:folder>
</view:view>

In the snippet above, you see a folder is being added, containing a single freemarker template file. You can add multiple files/folders on the top level or in folders this way. You probably also noticed a couple of aspects that were set on the new folder, and their actual values. For more examples, check out the spaces.xml file. They're are several good examples to be found on the classpath already, see the /alfresco/bootstrap folder.


Import strategy


If you know the UUID(s) of the spaces/files you're importing, you can choose out of a number of import strategies.


Note, if you're using XML, you'll have to manually add a 'sys:node-uuid' tag to that node. (generated ACP files automatically contain the UUID's)

Example:


                <view:properties>
                    <sys:node-uuid>b7c6b88a-e5fd-4ccf-b134-69a2460c3b89</sys:node-uuid>
                    ...
                </view:properties>
            </cm:content>
        </cm:contains>
    </cm:folder>
</view:view>

CREATE_NEW, CREATE_NEW_WITH_UUID, REMOVE_EXISTING, REPLACE_EXISTING, UPDATE_EXISTING, THROW_ON_COLLISION
(org.alfresco.service.cmr.view.ImporterBinding.UUID_BINDING)

See ACP#Import UUID Bindings for a more detailed explanation.

You can add these as follows:


  • global for the entire bean


<bean id='myModule.bootstrap'
      class='org.alfresco.repo.module.ImporterModuleComponent'
      parent='module.baseComponent'>
          <property name='uuidBinding'>
            <value>REPLACE_EXISTING</value>
          </property>
          ...

  • per BootstrapView

   <property name='bootstrapViews'>
      <list>
          <props>
               <prop key='uuidBinding'>UPDATE_EXISTING</prop>
               <prop key='path'>/${spaces.company_home.childname}/${spaces.dictionary.childname}</prop>
               <prop key='location'>alfresco/module/yourmodule/bootstrap/myimport.acp</prop>
           </props>
           ...
      </list>
   </property>
</bean>

Space Names Reference


The following are the substitution tokens that can be used for bootstrapping purposes.  These tokens can be redefined in the configuration files if needed. 


  • spaces.store=workspace://SpacesStore
  • spaces.company_home.childname=Company Home
  • spaces.guest_home.childname=Guest Home
  • spaces.dictionary.childname=Data Dictionary
  • spaces.templates.childname=Space Templates
  • spaces.templates.content.childname=Content Templates
  • spaces.templates.email.childname=Email Templates
  • spaces.templates.rss.childname=RSS Templates
  • spaces.savedsearches.childname=Saved Searches
  • spaces.scripts.childname=Scripts
  • spaces.wcm.childname=WCM
  • spaces.wcm_content_forms.childname=Web Forms
  • spaces.content_forms.childname=Web Forms
  • spaces.user_homes.childname=User Homes