Saturday, November 5, 2016

Import and Export of Alfresco ACP Files in Share 5.x

 Alfresco Content Package (ACP) files provide an efficient way to snapshot part of the Alfresco repository tree and then later recreate that snapshot of the tree in another part of the repository or in a totally different Alfresco repository.  It's a quick way to replicate and move the content, metadata and folder structure created in one repository into another one.  For relatively low volumes of data, ACP files are also a good way to import data into Alfresco from other systems.  ACP files are also a good way to bootstrap data that might be needed as part of an extension or customization included in an Alfresco module.

In the 3.x and 4.x versions of Alfresco, the ability to import and export ACP files was available from the user interface of the Alfresco Explorer client.  But starting in version 5.x, the Explorer client is no longer available and, unfortunately, the ability to import and export ACP files is not available from the standard Alfresco Share UI. (Although this is a feature that is available within the Alfresco Records Management Share extension).

An ACP file consists of an XML file and a directory that contains the flat list of files for the exported content.  Note that the files exported into the ACP are renamed to avoid any naming conflicts with the original content file names. The XML file represents the complete description of the exported folder hierarchy and the metadata of the folders and documents.  References in the XML identify and match metadata with the files stored in the exported folder of content. 

Alfresco does provide an easy way to programmatically export and import ACP files.  'Import' and 'Export' are Alfresco repository actions that can be accessed from server side Javascript code.  For example, you can easily write a rule in Javascript that can call either the import or export actions.

First, let's look at the Javascript code needed to create a simple export.  In this example, the entire contents of the document library for the default Alfresco Share site called Sample: Web Site Design Project is exported to an ACP file called ACPexport.acp.  The path to the area being exported from the Alfresco root directory is /companyhome/Sites/swsdp/documentLibrary.  The ACP file is written to the top of the repository (companyhome).

  // Export ACP  
   var nodeToExport = companyhome.childByNamePath("Sites/swsdp/documentLibrary")  
   var exportAction= actions.create("export");  
   exportAction.parameters['store'] = "workspace://SpacesStore";  
   exportAction.parameters['package-name'] = "ACPexport";  
   exportAction.parameters['destination'] = companyhome;  
   exportAction.parameters['include-children'] = true;  
   exportAction.parameters['include-self'] = false;  
   exportAction.parameters['encoding'] = "UTF-8";  
   exportAction.execute(nodeToExport);  

Now, as a simple example to import this ACP file, let's create a new site called swsdp2.The target location that the previously exported ACP file will be imported into is the document library of this new site.

 // Import ACP  
   var targetNodeForImport = companyhome.childByNamePath("Sites/swsdp2/documentLibrary");  
   var ACPFile = companyhome.childByNamePath("ACPexport.acp");  
   var importAction = actions.create("import");  
   importAction.parameters.encoding = "UTF-8";  
   importAction.parameters.destination = targetNodeForImport;  
   importAction.execute(ACPFile);  

After running this script, we get a copy of all of the content that was exported into the ACP file: the folders, documents and metadata that were in the original site.

This Javascript code can be run in the Javascript console, as part of a webscript, or as a rule associated with a folder.

8 comments:

  1. Hi:

    I run the first snipplet in JS Console in Alfresco 5.1.e and Alfresco 5.0.2.5, but I had the following error:


    Caused by: java.lang.NoSuchMethodError: org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream.setUseZip64(Lorg/apache/commons/compress/archivers/zip/Zip64Mode;)V

    I did not test the second part. The snipplet would be very useful because, this addon is not working in Alfresco 5, neither.

    https://addons.alfresco.com/addons/importexport-acpzip-share

    Regards.

    --C.

    ReplyDelete
  2. Hi Cesar,

    I suspect that something is wrong with your install.
    Did you install from a standard Alfresco stack?

    The error that you report is that it isn't finding a Java class file.

    The jar file where that file is located is here:
    alfresco/tomcat/webapps/alfresco/WEB-INF/lib/commons-compress-1.8.jar
    Check that this file exists.

    I tried running the code again on an Ubuntu machine using Alfresco 5.0.2.5. Earlier I had used Alfresco 5.1. I also have RM 2.4 installed and the Javascript console. Otherwise, it is a freshly installed system.

    I copy and pasted the same code listed above and it ran successfully.

    Try running the code on a system installed from the standard Alfresco stack.

    That should work -- and then try to see what is different between it and your current install.

    ReplyDelete
  3. Thank you very much Dick for your answer:

    I finally found the problem. I had an AMP module with an older version of common-compress between its dependencies, so two different versions of the same library were loaded in WEB-INF/lib. The older version did not have this class. Once deleted this wrong lib, all worked fine.

    Regards.

    --C.

    ReplyDelete
  4. Hi Dick,

    Thanks for writing this blog. I have no idea why Alfresco took the acp export out of share, it was a very important feature when developing apps. I did not realise that you could run the js code to do this so this info will come in very handy.

    Regards

    Brian O'Neill (Seed IM)

    ReplyDelete
  5. hi,
    great post,
    i run the first script in alfresco comunnity edicion 201609 and givme this error.

    500 Internal Error
    Stacktrace-Details:
    org.springframework.extensions.webscripts.WebScriptException: 11200270 Wrapped Exception (with status template): 11200298 Failed to execute script 'Javascript Console Script':
    ### Error querying database. Cause: java.sql.SQLException: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='
    ### The error may exist in alfresco/ibatis/#resource.dialect#/node-common-SqlMap.xml
    ### The error may involve alfresco.node.select_ChildAssocOfParentByName-Inline
    ### The error occurred while setting parameters
    ### SQL: select assoc.id as id, parentNode.id as parentNodeId, parentNode.version as parentNodeVersion, parentStore.protocol as parentNodeProtocol, parentStore.identifier as parentNodeIdentifier, parentNode.uuid as parentNodeUuid, childNode.id as childNodeId, childNode.version as childNodeVersion, childStore.protocol as childNodeProtocol, childStore.identifier as childNodeIdentifier, childNode.uuid as childNodeUuid, assoc.type_qname_id as type_qname_id, assoc.child_node_name_crc as child_node_name_crc, assoc.child_node_name as child_node_name, assoc.qname_ns_id as qname_ns_id, assoc.qname_localname as qname_localname, assoc.is_primary as is_primary, assoc.assoc_index as assoc_index from alf_child_assoc assoc join alf_node parentNode on (parentNode.id = assoc.parent_node_id) join alf_store parentStore on (parentStore.id = parentNode.store_id) join alf_node childNode on (childNode.id = assoc.child_node_id) left join alf_store childStore on (childStore.id = childNode.store_id) where parentNode.id = ? and assoc.type_qname_id = ? and assoc.child_node_name = ? and assoc.child_node_name_crc = ?
    ### Cause: java.sql.SQLException: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation '='

    What could be the error and the fault, thanks for the help

    ReplyDelete
  6. Hi Camilo,

    I haven't seen that error before. Looking at it, it seems to be coming from MySQL. It is likely happening because of non-English characters stored with your content.

    I found a suggestion here: http://stackoverflow.com/questions/1008287/illegal-mix-of-collations-mysql-error

    I would suggest that you review that article.
    Based on the discussion there and if it makes sense, you might try to do a backup of your database and then attempt the following:

    SET collation_connection = 'utf8_general_ci'

    then for your databases:

    ALTER DATABASE alfresco CHARACTER SET utf8 COLLATE utf8_general_ci

    ALTER TABLE alf_child_assoc CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci

    ALTER TABLE alf_node CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci

    ALTER TABLE alf_store CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci

    ReplyDelete
  7. Hi, I wrote:
    exportAction.parameters['destination'] = search.luceneSearch("TYPE:\"{http://www.alfresco.org/model/content/1.0}folder\" AND PATH:\"/app:company_home//cm:logs");

    and the error is:
    ReferenceError: "logs" is not defined. (workspace://SpacesStore/45d5f44a-390f-45b5-9f7e-52fe767f207a#12

    any idea?

    Thnks!

    ReplyDelete
  8. The escaping of your quotes at the end of the search expression don't seem to be right. The following worked OK for me:

    var doc = search.luceneSearch("TYPE:\"{http://www.alfresco.org/model/content/1.0}folder\" AND PATH:\"/app:company_home//cm:logs\"");

    ReplyDelete