Movatterモバイル変換


[0]ホーム

URL:


In: content-servicesIn: All docs
Close
Alfresco Content Services

ReST API Java Wrapper Extension Point

One of the libraries provided by theSDK for out-of-process extensionsis the Java ReST API wrapper library. It enables you to work with theAlfresco ReST APIfrom a Java client with standard Java classes. There is no need to parse JSON or create HTTP requests.

To set up a project with the Java ReST API library follow theseinstructions.

Common parameters

There are some common parameters in the different API calls. They are documented here instead of repeating the docs forthem under multiple sections:

ParameterDescriptionUsage
includeUse this parameter to return additional information about the node. The following optional fields can be requested:allowableOperations,aspectNames,association,isLink,isFavorite,isLocked,path,properties,permissions.List<String> include = new ArrayList<>(); include.add("permissions");
fieldsYou can use this parameter to restrict the fields returned within a response if, for example, you want to save on overall bandwidth. The list applies to a returned individual entity or entries within a collection. If the API method also supports theinclude parameter, then the fields specified ininclude parameter are returned in addition to those specified in thefields parameter.List<String> fields = new ArrayList<>(); fields.add("content,createdAt");
Note that all fields have to be added as one item comma separated.
whereOptionally filter the node list.Here are some examples:
(isFolder=true)
(isFile=true)
(nodeType='my:specialNodeType')
(nodeType='my:specialNodeType INCLUDESUBTYPES')
(id BETWEEN ('1', '79'))
includeSourceAlso includesource in addition toentries with folder information on the parent node – either the specified parent nodeId, or as resolved byrelativePathBoolean includeSource = false;
orderByA string to control the order of the entities returned in a list. The default sort order for the returned list is for folders to be sorted before files, and by ascending name. You can override the default usingorderBy to specify one or more fields to sort by. The default order is always ascending, but you can use an optionalASC orDESC modifier to specify an ascending or descending sort order. For example, specifyingorderBy=name DESC returns a mixed folder/file list in descending name order. You can use any of the following fields to order the results:isFolder,name,mimeType,nodeType,sizeInBytes,modifiedAt,createdAt,modifiedByUser,createdByUserList<String> orderBy = new ArrayList<>(); orderBy.add("title");
skipCountThe number of entities that exist in the collection before those included in this list, useful when implementing paging scenarios. If not supplied then the default value is0.Integer skipCount = 0;
maxItemsThe maximum number of items to return in the list, useful when implementing paging scenarios. If not supplied then the default value is100.Integer maxItems = 100;
autoRenameIftrue, then a name clash will cause an attempt to auto rename by finding a unique name using an integer suffix.Boolean autoRename = true;
versioningEnabledShould versioning of files be enabled at all?Boolean versioningEnabled = true;
majorVersionIftrue, then it will be a major version, such as 1.0, 2.0 etc. Iffalse, then the version change will be 1.1, 1.2, which is a minor version change.Boolean majorVersion = true;
updateCommentAdd a version comment which will appear in version history. Setting this parameter also enables versioning of this node, if it is not already versioned.String updateComment = "A comment";
updatedNameOptional new name of the node, setscm:name. This should include the file extension. The name must not contain spaces or the following special characters:* " < > \ / ? : |. The character. must not be used at the end of the name.String updatedName = null; if not updating or set to new name.

=== Managing Folders and Files ===

The following sections walk through how to use the Java ReST API wrapper services when managing folders and files.

List contents of a folder

To list contents of a folder in the repository use thelistNodeChildren method of theNodesApi,which is one of the main APIs used when you want to manipulate folders and files.

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class ListFolderContent {    static final Logger LOGGER = LoggerFactory.getLogger(ListFolderContent.class);    @Autowired    NodesApi nodesApi;    public void execute() throws IOException {        NodeChildAssociationPagingList nodes = listFolderContent("-root-", null);        NodeChildAssociationPagingList nodes2 = listFolderContent("-root-", "/Data Dictionary");    }    /**     * List contents (i.e. folders and files) of a folder.     *     * @param rootNodeId         the id of the folder node that is the root. If relativeFolderPath is null, then content in this folder will be listed. Besides node ID the aliases -my-, -root- and -shared- are also supported.     * @param relativeFolderPath path relative rootNodeId, if this is not null, then the content of this folder will be listed     * @return a list of child node objects contained in the folder, or null if not found     */    private NodeChildAssociationPagingList listFolderContent(String rootNodeId, String relativeFolderPath) {        Integer skipCount = 0;        Integer maxItems = 100;        List<String> include = null;        List<String> fields = null;        List<String> orderBy = null;        String where = null;        Boolean includeSource = false;        LOGGER.info("Listing folder {}{}", rootNodeId, relativeFolderPath);        NodeChildAssociationPagingList result = nodesApi.listNodeChildren(rootNodeId, skipCount, maxItems, orderBy, where, include,                relativeFolderPath, includeSource, fields).getBody().getList();        for (NodeChildAssociationEntry childNodeAssoc: result.getEntries()) {            LOGGER.info("Found node [name=" + childNodeAssoc.getEntry().getName() + "]");        }        return result;    }}

See alsomanage associations for information on how to list secondary child associations for a node.

Filter contents of a folder

To filter listed contents of a folder in the repository use thelistNodeChildren method of theNodesApiand set thewhere clause parameter.

More info about this ReST API endpoint

For a description of the common parameters, such aswhere andinclude, see thissection.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class ListFolderContent {    static final Logger LOGGER = LoggerFactory.getLogger(ListFolderContent.class);    @Autowired    NodesApi nodesApi;    public void execute() throws IOException {        NodeChildAssociationPagingList nodes = listFolderContent("-root-", null);        NodeChildAssociationPagingList nodes2 = listFolderContent("-root-", "/Data Dictionary");    }    /**     * List sub-folders of a folder.     *     * @param rootNodeId         the id of the folder node that is the root. If relativeFolderPath is null, then content in this folder will be listed. Besides node ID the aliases -my-, -root- and -shared- are also supported.     * @param relativeFolderPath path relative rootNodeId, if this is not null, then the content of this folder will be listed     * @return a list of child folder node objects contained in the folder, or null if not found     */    private NodeChildAssociationPagingList listFolderContent(String rootNodeId, String relativeFolderPath) {        Integer skipCount = 0;        Integer maxItems = 100;        List<String> include = null;        List<String> fields = null;        List<String> orderBy = null;        String where = "(isFolder=true)";        Boolean includeSource = false;        LOGGER.info("Listing folder {}{} with filter {}", rootNodeId, relativeFolderPath, where);        NodeChildAssociationPagingList result = nodesApi.listNodeChildren(rootNodeId, skipCount, maxItems, orderBy, where, include,                relativeFolderPath, includeSource, fields).getBody().getList();        for (NodeChildAssociationEntry childNodeAssoc: result.getEntries()) {            LOGGER.info("Found folder node [name=" + childNodeAssoc.getEntry().getName() + "]");        }        return result;    }}

Get folder/file metadata

To get metadata for a node, such as a file or folder, in the repository use thegetNode method of theNodesApi,which is one of the main APIs used when you want to manipulate folders and files.

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.NodeEntry;import org.alfresco.core.model.Node;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class GetNodeMetadataCmd {    static final Logger LOGGER = LoggerFactory.getLogger(GetNodeMetadataCmd.class);    @Autowired    NodesApi nodesApi;    public void execute() throws IOException {        Node node = getNode("-root-", null);        Node node2 = getNode("-root-", "/Data Dictionary");    }    /**     * Get a node (file/folder).     *     * @param nodeId             the id of the node that we want to fetch metadata for. If relativeFolderPath is specified, then metadata for this node will be returned. Besides node ID the aliases -my-, -root- and -shared- are also supported.     * @param relativeFolderPath A path relative to the nodeId, if this is not null, then metadata is returned on the node resolved by this path     * @return Node object if exist, or null if does not exist     */    private Node getNode(String nodeId,                         String relativeFolderPath) {        List<String> include = null;        List<String> fields = null;        NodeEntry result = nodesApi.getNode(nodeId, include, relativeFolderPath, fields).getBody();        LOGGER.info("Got node {}", result.getEntry());        return result.getEntry();    }}

Executing this code would give the following result:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar get-node                                               2021-04-29 08:09:22.215  INFO 18370 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.536 seconds (JVM running for 4.449)2021-04-29 08:09:22.217  INFO 18370 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: get-node2021-04-29 08:09:22.485  INFO 18370 --- [           main] o.a.tutorial.restapi.GetNodeMetadataCmd  : Got node class Node {    id: e439190c-3fe0-48a1-8a9a-374fbc54b570    name: Company Home    nodeType: cm:folder    isFolder: true    isFile: false    isLocked: false    modifiedAt: 2021-04-28T11:48:08.325Z    modifiedByUser: class UserInfo {        displayName: System        id: System    }    createdAt: 2021-04-28T11:47:59.098Z    createdByUser: class UserInfo {        displayName: System        id: System    }    parentId: null    isLink: null    isFavorite: null    content: null    aspectNames: [cm:titled, cm:auditable, app:uifacets]    properties: {cm:title=Company Home, cm:description=The company root space, app:icon=space-icon-default}    allowableOperations: null    path: null    permissions: null    definition: null}2021-04-29 08:09:22.538  INFO 18370 --- [           main] o.a.tutorial.restapi.GetNodeMetadataCmd  : Got node class Node {    id: 1219e0ff-941f-49df-9151-997b84a8359b    name: Data Dictionary    nodeType: cm:folder    isFolder: true    isFile: false    isLocked: false    modifiedAt: 2021-04-28T11:48:17.700Z    modifiedByUser: class UserInfo {        displayName: System        id: System    }    createdAt: 2021-04-28T11:47:59.199Z    createdByUser: class UserInfo {        displayName: System        id: System    }    parentId: e439190c-3fe0-48a1-8a9a-374fbc54b570    isLink: null    isFavorite: null    content: null    aspectNames: [cm:titled, cm:auditable, app:uifacets]    properties: {cm:title=Data Dictionary, cm:description=User managed definitions, app:icon=space-icon-default}    allowableOperations: null    path: null    permissions: null    definition: null}

See alsomanage associations for information on how to list associations for a node.

Create a folder

To create a folder in the repository use thecreateNode method of theNodesApi,which is one of the main APIs used when you want to manipulate folders and files.

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.Node;import org.alfresco.core.model.NodeBodyCreate;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.*;@Componentpublic class CreateFolder {    static final Logger LOGGER = LoggerFactory.getLogger(CreateFolder.class);    @Autowired    NodesApi nodesApi;    public void execute() throws IOException {        Node folderInCompanyHome = createFolder("Folder1", "Title1", "Desc1", "");        Node folderInFolder1 = createFolder("Folder2", "Title2", "Desc2", "/Folder1");    }    /**     * Make the remote call to create a folder in the repository, if it does not exist.     *     * @param folderName         the name of the folder     * @param folderTitle        the title of the folder     * @param folderDescription  the description of the folder     * @param relativeFolderPath path relative to /Company Home     * @return a node object for the newly created node, contains the ID,     * such as e859588c-ae81-4c5e-a3b6-4c6109b6c905     */    private Node createFolder(String folderName,                              String folderTitle,                              String folderDescription,                              String relativeFolderPath) throws IOException {        Objects.requireNonNull(folderName);        String rootPath = "-root-";       // /Company Home        String folderType = "cm:folder";  // Standard out-of-the-box folder type        List<String> folderAspects = new ArrayList<String>();        folderAspects.add("cm:titled");        Map<String, String> folderProps = new HashMap<>();        folderProps.put("cm:title", folderTitle);        folderProps.put("cm:description", folderDescription);                String nodeId = rootPath; // The id of a node. You can also use one of these well-known aliases: -my-, -shared-, -root-        NodeBodyCreate nodeBodyCreate = new NodeBodyCreate();        nodeBodyCreate.setName(folderName);        nodeBodyCreate.setNodeType(folderType);        nodeBodyCreate.setAspectNames(folderAspects);        nodeBodyCreate.setProperties(folderProps);        nodeBodyCreate.setRelativePath(relativeFolderPath);        List<String> include = null;        List<String> fields = null;        Boolean autoRename = true;        Boolean majorVersion = true;        // Should versioning be enabled at all?        Boolean versioningEnabled = true;        Node folderNode = nodesApi.createNode(nodeId, nodeBodyCreate, autoRename, majorVersion, versioningEnabled,                include, fields).getBody().getEntry();        LOGGER.info("Created new folder: {}", folderNode);        return folderNode;    }}

See alsomanage associations for more examples of node creation.

Upload a file

To upload a file to the repository use first theNodesApi.createNodemethod, which will create the metadata for the file, and then theNodesApi.updateNodeContentmethod that will set the content for the file.

At the moment it’s necessary to make two calls to upload a file, but enhancements are being developed in a new versionof SDK 5 to provide a one method approach as this issupported in the ReST API.

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.Node;import org.alfresco.core.model.NodeBodyCreate;import org.apache.commons.io.FileUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;@Componentpublic class CreateFile {    static final Logger LOGGER = LoggerFactory.getLogger(CreateFile.class);    private List<String> include = null;    private List<String> fields = null;    private String contentType = "cm:content"; // Out-of-the-box content type for generic file content    private Boolean autoRename = true;    private Boolean majorVersion = true;    private Boolean versioningEnabled = true;    private String updateComment = null;    private String updatedName = null;    @Autowired    NodesApi nodesApi;    public void execute() throws IOException {        // Create a text file under the /Company Home/Guest Home folder        Node newTextFile = createTextFile("-root-", "somestuff.txt", "TextfileTitle",                "TextfileDesc", "/Guest Home", "Some text for the file");        // Upload a file from disk to the '/Company Home/Guest Home' folder, the file that is being uploaded, 'somepicture.png'         // in this case, is located in the same directory as we are running the app from        Node newFile = uploadFile("-root-", "somepicture.png", "PicturefileTitle",                "PicturefileDesc", "/Guest Home", "somepicture.png");    }    /**     * Upload a file from disk     */    private Node uploadFile(String parentFolderId, String fileName, String title, String description,                            String relativeFolderPath, String filePath) {        Node fileNode = createFileMetadata(parentFolderId, fileName, title, description, relativeFolderPath);        // Get the file bytes        File someFile = new File(filePath);        byte[] fileData = null;        try {            fileData = FileUtils.readFileToByteArray(someFile);        } catch (IOException e) {            e.printStackTrace();        }        // Add the file node content        Node updatedFileNode = nodesApi.updateNodeContent(fileNode.getId(),                fileData, majorVersion, updateComment, updatedName, include, fields).getBody().getEntry();        LOGGER.info("Created file with content: {}", updatedFileNode.toString());        return updatedFileNode;    }    /**     * Create a text file     */    private Node createTextFile(String parentFolderId, String fileName, String title, String description,                                String relativeFolderPath, String textContent) {        Node fileNode = createFileMetadata(parentFolderId, fileName, title, description, relativeFolderPath);        // Add the file node content        Node updatedFileNode = nodesApi.updateNodeContent(fileNode.getId(),                textContent.getBytes(), majorVersion, updateComment, updatedName, include, fields).getBody().getEntry();        LOGGER.info("Created file with content: {}", updatedFileNode.toString());        return updatedFileNode;    }    /**     * Create metadata for a file node     *     * @param parentFolderId the parent folder node ID where the file should be stored     * @param fileName the name for the new file     * @param title the title property value for the new file     * @param description the description property value for the new file     * @param relativeFolderPath path relative to /Company Home     * @return a Node object with file metadata and the Node ID     */    private Node createFileMetadata(String parentFolderId, String fileName, String title, String description,                                    String relativeFolderPath) {        List<String> fileAspects = new ArrayList<String>();        fileAspects.add("cm:titled");        Map<String, String> fileProps = new HashMap<>();        fileProps.put("cm:title", title);        fileProps.put("cm:description", description);                NodeBodyCreate nodeBodyCreate = new NodeBodyCreate();        nodeBodyCreate.setName(fileName);        nodeBodyCreate.setNodeType(contentType);        nodeBodyCreate.setAspectNames(fileAspects);        nodeBodyCreate.setProperties(fileProps);        nodeBodyCreate.setRelativePath(relativeFolderPath);        // Create the file node metadata        Node fileNode = nodesApi.createNode(parentFolderId, nodeBodyCreate, autoRename, majorVersion, versioningEnabled,                include, fields).getBody().getEntry();        return fileNode;    }}

See alsomanage associations for more examples of uploading and creating nodes.

Upload a file with custom type

Uploading a file with a custom type to the Repository means creating a node with a type other thancm:content. Seeupload a file for info on how to upload a file with the out-of-the-box content typecm:content set.There’s actually not much difference to how you upload a file with a custom type. Let’s say we have a content model typeacme:document and an aspectacme:securityClassified and these are defined as follows:

<type name="acme:document">   <title>Sample Document Type</title>   <parent>cm:content</parent>   <properties>       <property name="acme:documentId">           <title>Document Identification Number</title>           <type>d:text</type>       </property>   </properties>   <mandatory-aspects>       <aspect>acme:securityClassified</aspect>   </mandatory-aspects></type><aspect name="acme:securityClassified">    <title>ACME Security Classified</title>    <description>Content has been security classified</description>    <properties>        <property name="acme:securityClassification">            <type>d:text</type>            <index enabled="true">                <atomic>true</atomic>                <stored>false</stored>                <tokenised>false</tokenised>            </index>            <constraints>                <constraint ref="acme:securityClassificationOptions"/>            </constraints>        </property>    </properties></aspect>

We got two custom propertiesacme:documentId andacme:securityClassification. For more information on how toimplement and deploy this custom content model seethis documentation.

Now, to upload a file and set this custom type and aspect we use the same code as forupload a file withminor updates to thecontentType variable and thecreateFileMetadata method:

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.Node;import org.alfresco.core.model.NodeBodyCreate;import org.apache.commons.io.FileUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;@Componentpublic class CreateFileCustomTypeCmd {    static final Logger LOGGER = LoggerFactory.getLogger(CreateFileCustomTypeCmd.class);    private String contentType = "acme:document"; // Set custom content type    private Boolean autoRename = true;    private Boolean majorVersion = true;    private Boolean versioningEnabled = true;    private String updateComment = null;    private String updatedName = null;    private List<String> include = null;    private List<String> fields = null;    @Autowired    NodesApi nodesApi;    public void execute() throws IOException {        // Create a text file under the /Company Home/Guest Home folder        Node newTextFile = createTextFile("-root-", "somestuff2.txt", "TextfileTitle2",                "TextfileDesc2", "/Guest Home", "Some text for the file2");        // Upload a file from disk to the /Company Home/Guest Home folder, file resides in app dir        Node newFile = uploadFile("-root-", "somepicture2.png", "PicturefileTitle2",                "PicturefileDesc2", "/Guest Home", "somepicture.png");    }    /**     * Upload a file from disk     */    private Node uploadFile(String parentFolderId, String fileName, String title, String description,                            String relativeFolderPath, String filePath) {        Node fileNode = createFileMetadata(parentFolderId, fileName, title, description, relativeFolderPath);        // Get the file bytes        File someFile = new File(filePath);        byte[] fileData = null;        try {            fileData = FileUtils.readFileToByteArray(someFile);        } catch (IOException e) {            e.printStackTrace();        }        // Add the file node content        Node updatedFileNode = nodesApi.updateNodeContent(fileNode.getId(),                fileData, majorVersion, updateComment, updatedName, include, fields).getBody().getEntry();        LOGGER.info("Created file with content: {}", updatedFileNode.toString());        return updatedFileNode;    }    /**     * Create a text file     */    private Node createTextFile(String parentFolderId, String fileName, String title, String description,                                String relativeFolderPath, String textContent) {        Node fileNode = createFileMetadata(parentFolderId, fileName, title, description, relativeFolderPath);        // Add the file node content        Node updatedFileNode = nodesApi.updateNodeContent(fileNode.getId(),                textContent.getBytes(), majorVersion, updateComment, updatedName, include, fields).getBody().getEntry();        LOGGER.info("Created file with content: {}", updatedFileNode.toString());        return updatedFileNode;    }    /**     * Create metadata for a file node     *     * @param parentFolderId the parent folder node ID where the file should be stored     * @param fileName the name for the new file     * @param title the title property value for the new file     * @param description the description property value for the new file     * @param relativeFolderPath path relative to /Company Home     * @return a Node object with file metadata and the Node ID     */    private Node createFileMetadata(String parentFolderId, String fileName, String title, String description,                                    String relativeFolderPath) {        List<String> fileAspects = new ArrayList<String>();        fileAspects.add("cm:titled");        fileAspects.add("acme:securityClassified");        Map<String, String> fileProps = new HashMap<>();        fileProps.put("cm:title", title);        fileProps.put("cm:description", description);        fileProps.put("acme:documentId", "DOC-001");                          // custom prop from type        fileProps.put("acme:securityClassification", "Company Confidential"); // custom prop from aspect                NodeBodyCreate nodeBodyCreate = new NodeBodyCreate();        nodeBodyCreate.setName(fileName);        nodeBodyCreate.setNodeType(contentType);        nodeBodyCreate.setAspectNames(fileAspects);        nodeBodyCreate.setProperties(fileProps);        nodeBodyCreate.setRelativePath(relativeFolderPath);        // Create the file node metadata        Node fileNode = nodesApi.createNode(parentFolderId, nodeBodyCreate, autoRename, majorVersion, versioningEnabled,                include, fields).getBody().getEntry();        return fileNode;    }}

See alsomanage associations for more examples of uploading and creating nodes.

Upload a new version of file

To upload a new version of a file to the repository use theNodesApi.updateNodeContentmethod, which will set the new content for the file.

More info about this ReST API endpoint

For a description of the common parameters, such asmajorVersion, see thissection.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.Node;import org.alfresco.core.model.NodeBodyCreate;import org.apache.commons.io.FileUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;@Componentpublic class UploadNewFileVersionCmd {    static final Logger LOGGER = LoggerFactory.getLogger(UploadNewFileVersionCmd.class);        private Boolean majorVersion = true;    private String updateComment = null;    private String updatedName = null;    private List<String> include = null;    private List<String> fields = null;    @Autowired    NodesApi nodesApi;    public void execute(String textFileNodeId, String binFileNodeId) throws IOException {        // Update text content for a file        Node newTextFile = updateTextFileContent(textFileNodeId,"Some UPDATED text for the file");        // Upload a file as new content        Node newFile = uploadNewFileVersion(binFileNodeId, "updatedpicture.png");    }    /**     * Upload a file from disk as a new version     */    private Node uploadNewFileVersion(String fileNodeId, String filePath) {        // Get the file bytes        File someFile = new File(filePath);        byte[] fileData = null;        try {            fileData = FileUtils.readFileToByteArray(someFile);        } catch (IOException e) {            e.printStackTrace();        }        // Update the file node content        Node updatedFileNode = nodesApi.updateNodeContent(fileNodeId,                fileData, majorVersion, updateComment, updatedName, include, fields).getBody().getEntry();        LOGGER.info("Uploaded new content for file: {}", updatedFileNode.toString());        return updatedFileNode;    }    /**     * Update text content for a file     */    private Node updateTextFileContent(String fileNodeId, String textContent) {        // Update the file node content        Node updatedFileNode = nodesApi.updateNodeContent(fileNodeId,                textContent.getBytes(), majorVersion, updateComment, updatedName, include, fields).getBody().getEntry();        LOGGER.info("Updated text content for file: {}", updatedFileNode.toString());        return updatedFileNode;    }}

We would execute this command class something like this, passing in the command name, text file Node ID, and thebinary file node id:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar upload-new-version 0492460b-6269-4ca1-9668-0d934d2f3370 48413f7a-066d-4e38-b2e6-c84ede6354932021-04-28 13:44:51.437  INFO 15466 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 2.782 seconds (JVM running for 3.471)2021-04-28 13:44:51.439  INFO 15466 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: upload-new-version2021-04-28 13:44:51.441  INFO 15466 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 0492460b-6269-4ca1-9668-0d934d2f33702021-04-28 13:44:51.441  INFO 15466 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: 48413f7a-066d-4e38-b2e6-c84ede6354932021-04-28 13:44:51.981  INFO 15466 --- [           main] o.a.t.restapi.UploadNewFileVersionCmd    : Updated text content for file: class Node {    id: 0492460b-6269-4ca1-9668-0d934d2f3370    name: somestuff2.txt    nodeType: acme:document    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-04-28T12:44:51.578Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-28T12:02:33.143Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: 8fa4e27d-35aa-411d-8bbe-831b6ed0c445    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: text/plain        mimeTypeName: Plain Text        sizeInBytes: 30        encoding: ISO-8859-1    }    aspectNames: [rn:renditioned, cm:versionable, cm:titled, cm:auditable, acme:securityClassified, cm:author, cm:thumbnailModification]    properties: {cm:title=TextfileTitle2, cm:versionType=MAJOR, acme:documentId=DOC-001, cm:versionLabel=3.0, acme:securityClassification=Company Confidential, cm:lastThumbnailModification=[doclib:1619611506701], cm:description=TextfileDesc2}    allowableOperations: null    path: null    permissions: null    definition: null}2021-04-28 13:44:56.783  INFO 15466 --- [           main] o.a.t.restapi.UploadNewFileVersionCmd    : Uploaded new content for file: class Node {    id: 48413f7a-066d-4e38-b2e6-c84ede635493    name: somepicture2.png    nodeType: acme:document    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-04-28T12:44:52.055Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-28T12:02:33.621Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: 8fa4e27d-35aa-411d-8bbe-831b6ed0c445    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: image/png        mimeTypeName: PNG Image        sizeInBytes: 23174        encoding: UTF-8    }    aspectNames: [rn:renditioned, cm:versionable, cm:titled, cm:auditable, acme:securityClassified, cm:author, cm:thumbnailModification, exif:exif]    properties: {cm:title=PicturefileTitle2, cm:versionType=MAJOR, acme:documentId=DOC-001, cm:versionLabel=3.0, exif:pixelYDimension=256, acme:securityClassification=Company Confidential, exif:pixelXDimension=256, cm:lastThumbnailModification=[doclib:1619611506392, imgpreview:1619611515611], cm:description=PicturefileDesc2}    allowableOperations: null    path: null    permissions: null    definition: null}

Note how thecm:versionLabel has bumped up to3.0. Version 1.0 and 2.0 were created when the files werecreated in twosteps.

Get file version history

To get the version history for a file use theVersionsApi.listVersionHistorymethod, which will retrieve a list of all the node versions.

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.VersionsApi;import org.alfresco.core.model.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class ListVersionHistoryCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ListVersionHistoryCmd.class);    @Autowired    VersionsApi versionsApi;    public void execute(String fileNodeId) throws IOException {        VersionPagingList nodes = listVersionHistory(fileNodeId);    }        /**     * List the version history for a file node.     *     * @param fileNodeId the id of the file node     * @return a list of child node objects contained in the folder, or null if not found     */    private VersionPagingList listVersionHistory(String fileNodeId) {        Integer skipCount = 0;        Integer maxItems = 100;        List<String> include = null;        List<String> fields = null;        LOGGER.info("Listing versions for file node ID {}", fileNodeId);        VersionPagingList result = versionsApi.listVersionHistory(fileNodeId, include, fields, skipCount, maxItems).getBody().getList();        for (VersionEntry versionEntry: result.getEntries()) {            LOGGER.info("Node version " + versionEntry.getEntry().toString());        }        return result;    }}

We would execute this command class something like this, passing in the file Node ID:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar list-file-versions 0492460b-6269-4ca1-9668-0d934d2f3370                   2021-04-29 08:04:48.145  INFO 18326 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 6.498 seconds (JVM running for 7.686)2021-04-29 08:04:48.148  INFO 18326 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: list-file-versions2021-04-29 08:04:48.152  INFO 18326 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 0492460b-6269-4ca1-9668-0d934d2f33702021-04-29 08:04:48.152  INFO 18326 --- [           main] o.a.t.restapi.ListVersionHistoryCmd      : Listing versions for file node ID 0492460b-6269-4ca1-9668-0d934d2f33702021-04-29 08:04:48.990  INFO 18326 --- [           main] o.a.t.restapi.ListVersionHistoryCmd      : Node version class Version {    id: 3.0    versionComment: null    name: somestuff2.txt    nodeType: acme:document    isFolder: false    isFile: true    modifiedAt: 2021-04-28T12:44:51.578Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    content: class ContentInfo {        mimeType: text/plain        mimeTypeName: Plain Text        sizeInBytes: 30        encoding: ISO-8859-1    }    aspectNames: null    properties: null}2021-04-29 08:04:48.990  INFO 18326 --- [           main] o.a.t.restapi.ListVersionHistoryCmd      : Node version class Version {    id: 2.0    versionComment: null    name: somestuff2.txt    nodeType: acme:document    isFolder: false    isFile: true    modifiedAt: 2021-04-28T12:02:33.526Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    content: class ContentInfo {        mimeType: text/plain        mimeTypeName: Plain Text        sizeInBytes: 23        encoding: ISO-8859-1    }    aspectNames: null    properties: null}2021-04-29 08:04:48.990  INFO 18326 --- [           main] o.a.t.restapi.ListVersionHistoryCmd      : Node version class Version {    id: 1.0    versionComment: null    name: somestuff2.txt    nodeType: acme:document    isFolder: false    isFile: true    modifiedAt: 2021-04-28T12:02:33.143Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    content: class ContentInfo {        mimeType: text/plain        mimeTypeName: Plain Text        sizeInBytes: 0        encoding: UTF-8    }    aspectNames: null    properties: null}

Note theid property that contains the file version number. TheversionComment property would contain any commentsmade when uploading a new version of the file. Folder nodes does not have content.

Download a file

To download a file use theNodesApi.getNodeContentmethod, which will download the content bytes for the file.

More info about this ReST API endpoint

import org.alfresco.core.handler.NodesApi;import org.apache.commons.io.FileUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.io.Resource;import org.springframework.stereotype.Component;import java.io.File;import java.io.IOException;import java.time.OffsetDateTime;@Componentpublic class GetNodeContentCmd {    static final Logger LOGGER = LoggerFactory.getLogger(GetNodeContentCmd.class);    @Autowired    NodesApi nodesApi;    public void execute(String fileNodeId, String filePathOnDisk) throws IOException {        Resource nodeContent = getNodeContent(fileNodeId);        // Write file to disk        File targetFile = new File(filePathOnDisk);        FileUtils.copyInputStreamToFile(nodeContent.getInputStream(), targetFile);    }    /**     * Get a file node content bytes (folders does not have content).     *     * @param nodeId   the id of the file node that we want to fetch content for.     * @return Node content info object     */    private Resource getNodeContent(String nodeId) throws IOException {        // Relevant when using API call from web browser, true is the default        Boolean attachment = true;        // Only download if modified since this time, optional        OffsetDateTime ifModifiedSince = null;        // The Range header indicates the part of a document that the server should return.        // Single part request supported, for example: bytes=1-10., optional        String range = null;        Resource result = nodesApi.getNodeContent(nodeId, attachment, ifModifiedSince, range).getBody();        LOGGER.info("Got node {} size: {}", result.getFilename(), result.contentLength());        return result;    }}

Download multiple files

To download multiple files use theDownloadsApi.createDownloadmethod to create a ZIP download on the server side, then check the status of the ZIP download withDownloadsApi.getDownload.When the download is ready get it withNodesApi.getNodeConent

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.DownloadsApi;import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.Download;import org.alfresco.core.model.DownloadBodyCreate;import org.alfresco.core.model.DownloadEntry;import org.apache.commons.io.FileUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.io.Resource;import org.springframework.stereotype.Component;import java.io.File;import java.io.IOException;import java.time.OffsetDateTime;import java.util.List;@Componentpublic class GetMultipleNodeContentCmd {    static final Logger LOGGER = LoggerFactory.getLogger(GetMultipleNodeContentCmd.class);    @Autowired    DownloadsApi downloadsApi;    @Autowired    NodesApi nodesApi;    public void execute(String[] fileNodeIds, String zipFilePathOnDisk) throws IOException, InterruptedException {        DownloadEntry downloadEntry = createZipDownload(fileNodeIds);        Resource zipNodeContent = getNodeContent(downloadEntry.getEntry().getId());        // Write ZIP file to disk        File targetFile = new File(zipFilePathOnDisk);        FileUtils.copyInputStreamToFile(zipNodeContent.getInputStream(), targetFile);    }    /**     * Create a ZIP download with multiple file nodes. This method waits until download is ready.     *     * @param nodeIds   the node ids for the files we want to download in one ZIP     * @return download entry info object for the ZIP     */    private DownloadEntry createZipDownload(String[] nodeIds) throws InterruptedException {        List<String> fields = null;        // Set up POST data with node IDs we want to download        DownloadBodyCreate downloads = new DownloadBodyCreate();        for (String nodeId : nodeIds) {            downloads.addNodeIdsItem(nodeId);        }        // First create the download on the server side        DownloadEntry result = downloadsApi.createDownload(downloads, fields).getBody();        LOGGER.info("Created ZIP download: {}", result.getEntry().toString());        // Check the download status        DownloadEntry download = downloadsApi.getDownload(result.getEntry().getId(), fields).getBody();        while (!download.getEntry().getStatus().equals(Download.StatusEnum.DONE)) {            LOGGER.info("Checking ZIP download status: {}", download.getEntry().getStatus());            Thread.sleep(1000); // do nothing for 1000 milliseconds (1 second)            download = downloadsApi.getDownload(result.getEntry().getId(), fields).getBody();        }        LOGGER.info("ZIP download is READY: {}", result.getEntry().getId());        return download;    }    /**     * Get a file node content bytes (folders does not have content).     *     * @param nodeId   the id of the file node that we want to fetch content for.     * @return Node content info object     */    private Resource getNodeContent(String nodeId) throws IOException {        // Relevant when using API call from web browser, true is the default        Boolean attachment = true;        // Only download if modified since this time, optional        OffsetDateTime ifModifiedSince = null;        // The Range header indicates the part of a document that the server should return.        // Single part request supported, for example: bytes=1-10., optional        String range = null;        Resource result = nodesApi.getNodeContent(nodeId, attachment, ifModifiedSince, range).getBody();        LOGGER.info("Got node {} size: {}", result.getFilename(), result.contentLength());        return result;    }}

Executing the code gives a result looking something like this:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar get-multiple-file-content 0492460b-6269-4ca1-9668-0d934d2f3370 48413f7a-066d-4e38-b2e6-c84ede635493 mydownload.zip2021-04-29 12:58:53.560  INFO 19432 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 2.956 seconds (JVM running for 3.436)2021-04-29 12:58:53.562  INFO 19432 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: get-multiple-file-content2021-04-29 12:58:53.564  INFO 19432 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 0492460b-6269-4ca1-9668-0d934d2f33702021-04-29 12:58:53.564  INFO 19432 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: 48413f7a-066d-4e38-b2e6-c84ede6354932021-04-29 12:58:53.564  INFO 19432 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[3]: mydownload.zip2021-04-29 12:58:54.150  INFO 19432 --- [           main] o.a.t.restapi.GetMultipleNodeContentCmd  : Created ZIP download: class Download {    filesAdded: 0    bytesAdded: 0    id: b73c36e5-112b-48a0-baa6-fa225bd9d53d    totalFiles: 0    totalBytes: 0    status: PENDING}2021-04-29 12:58:54.167  INFO 19432 --- [           main] o.a.t.restapi.GetMultipleNodeContentCmd  : Checking ZIP download status: PENDING2021-04-29 12:58:55.194  INFO 19432 --- [           main] o.a.t.restapi.GetMultipleNodeContentCmd  : ZIP download is READY: b73c36e5-112b-48a0-baa6-fa225bd9d53d2021-04-29 12:58:55.223  INFO 19432 --- [           main] o.a.t.restapi.GetMultipleNodeContentCmd  : Got node archive.zip size: 23111

In this example we pass in two file node identifiers that will be requested in the zip download. The zip download filewill be stored in current directory under the namemydownload.zip. Note that right after we have initialized thecreation of the zip download there are no files added to the zip (filesAdded: 0), we have to wait for the zip downloadto be created on the server side. Then we can download with the usualgetNodeContent method.

List file renditions

To list content renditions for a file use theRenditionsApi.listRenditionsmethod.

More info about this ReST API endpoint

For a description of the common parameters, such aswhere, see thissection.

import org.alfresco.core.handler.RenditionsApi;import org.alfresco.core.model.RenditionEntry;import org.alfresco.core.model.RenditionPagingList;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class ListRenditionsCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ListRenditionsCmd.class);    @Autowired    RenditionsApi renditionsApi;    public void execute(String fileNodeId) throws IOException {        RenditionPagingList nodeRenditions = listRenditions(fileNodeId);    }        /**     * List renditions for a file node.     *     * @param fileNodeId the id of the file node     * @return a list of renditions, or null if not found     */    private RenditionPagingList listRenditions(String fileNodeId) {        String where = null; // filter renditions        LOGGER.info("Listing versions for file node ID {}", fileNodeId);        RenditionPagingList result = renditionsApi.listRenditions(fileNodeId, where).getBody().getList();        for (RenditionEntry renditionEntry: result.getEntries()) {            LOGGER.info("Node rendition: " + renditionEntry.getEntry().toString());        }        return result;    }}

Executing this code looks like this, here we are listing renditions for a text file:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar list-renditions 0492460b-6269-4ca1-9668-0d934d2f3370                 2021-04-29 13:58:25.387  INFO 19701 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.131 seconds (JVM running for 3.822)2021-04-29 13:58:25.389  INFO 19701 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: list-renditions2021-04-29 13:58:25.390  INFO 19701 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 0492460b-6269-4ca1-9668-0d934d2f33702021-04-29 13:58:25.391  INFO 19701 --- [           main] o.a.tutorial.restapi.ListRenditionsCmd   : Listing versions for file node ID 0492460b-6269-4ca1-9668-0d934d2f33702021-04-29 13:58:25.703  INFO 19701 --- [           main] o.a.tutorial.restapi.ListRenditionsCmd   : Node rendition: class Rendition {    id: avatar    content: class ContentInfo {        mimeType: image/png        mimeTypeName: PNG Image        sizeInBytes: null        encoding: null    }    status: NOT_CREATED}2021-04-29 13:58:25.703  INFO 19701 --- [           main] o.a.tutorial.restapi.ListRenditionsCmd   : Node rendition: class Rendition {    id: avatar32    content: class ContentInfo {        mimeType: image/png        mimeTypeName: PNG Image        sizeInBytes: null        encoding: null    }    status: NOT_CREATED}2021-04-29 13:58:25.703  INFO 19701 --- [           main] o.a.tutorial.restapi.ListRenditionsCmd   : Node rendition: class Rendition {    id: doclib    content: class ContentInfo {        mimeType: image/png        mimeTypeName: PNG Image        sizeInBytes: 222        encoding: UTF-8    }    status: CREATED}2021-04-29 13:58:25.703  INFO 19701 --- [           main] o.a.tutorial.restapi.ListRenditionsCmd   : Node rendition: class Rendition {    id: imgpreview    content: class ContentInfo {        mimeType: image/jpeg        mimeTypeName: JPEG Image        sizeInBytes: null        encoding: null    }    status: NOT_CREATED}2021-04-29 13:58:25.703  INFO 19701 --- [           main] o.a.tutorial.restapi.ListRenditionsCmd   : Node rendition: class Rendition {    id: medium    content: class ContentInfo {        mimeType: image/jpeg        mimeTypeName: JPEG Image        sizeInBytes: null        encoding: null    }    status: NOT_CREATED}2021-04-29 13:58:25.703  INFO 19701 --- [           main] o.a.tutorial.restapi.ListRenditionsCmd   : Node rendition: class Rendition {    id: pdf    content: class ContentInfo {        mimeType: application/pdf        mimeTypeName: Adobe PDF Document        sizeInBytes: 8472        encoding: UTF-8    }    status: CREATED}

We can see the renditionsid, such aspdf. Some renditions are for things you see in the UI, such asthumbnail and preview of document.

Get file rendition content

To get the content for a file rendition theRenditionsApi.getRenditionContentmethod, which will download the content bytes for the file rendition.

More info about this ReST API endpoint

import org.alfresco.core.handler.RenditionsApi;import org.apache.commons.io.FileUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.io.Resource;import org.springframework.stereotype.Component;import java.io.File;import java.io.IOException;import java.time.OffsetDateTime;@Componentpublic class GetRenditionContentCmd {    static final Logger LOGGER = LoggerFactory.getLogger(GetRenditionContentCmd.class);    @Autowired    RenditionsApi renditionsApi;    public void execute(String fileNodeId, String renditionId, String filePathOnDisk) throws IOException {        Resource nodeContent = getRenditionContent(fileNodeId, renditionId);        // Write rendition file to disk        File targetFile = new File(filePathOnDisk);        FileUtils.copyInputStreamToFile(nodeContent.getInputStream(), targetFile);    }    /**     * Get rendition content info.     *     * @param nodeId        the id for the node that the rendition is for     * @param renditionId   the id of the rendition that we want to fetch content for, such as doclib, pdf etc     * @return Rendition content info object     */    private Resource getRenditionContent(String nodeId, String renditionId) throws IOException {        // Relevant when using API call from web browser, true is the default        Boolean attachment = true;        // Only download if modified since this time, optional        OffsetDateTime ifModifiedSince = null;        // The Range header indicates the part of a rendition that the server should return.        // Single part request supported, for example: bytes=1-10., optional        String range = null;        // If true and there is no rendition for this nodeId and renditionId, then the placeholder image for the        // mimetype of this rendition is returned, rather than a 404 response        Boolean placeholder = false;        Resource result = renditionsApi.getRenditionContent(                nodeId, renditionId, attachment, ifModifiedSince, range, placeholder).getBody();        LOGGER.info("Got rendition {} size: {}", result.getFilename(), result.contentLength());        return result;    }}

Executing this code and getting apdf rendition for a text file looks like this:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar get-rendition-content 0492460b-6269-4ca1-9668-0d934d2f3370 pdf mytext.pdf 2021-04-29 16:05:25.501  INFO 20077 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.324 seconds (JVM running for 3.867)2021-04-29 16:05:25.504  INFO 20077 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: get-rendition-content2021-04-29 16:05:25.506  INFO 20077 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 0492460b-6269-4ca1-9668-0d934d2f33702021-04-29 16:05:25.506  INFO 20077 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: pdf2021-04-29 16:05:25.506  INFO 20077 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[3]: mytext.pdf2021-04-29 16:05:25.657  INFO 20077 --- [           main] o.a.t.restapi.GetRenditionContentCmd     : Got rendition pdf size: 8472

Update metadata for a folder or file

To update metadata for a node, such as a file or folder, use theNodesApi.updateNodemethod.

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.Node;import org.alfresco.core.model.NodeBodyUpdate;import org.alfresco.core.model.NodeEntry;import org.alfresco.core.model.PermissionsBody;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.HashMap;import java.util.List;import java.util.Map;@Componentpublic class UpdateNodeMetadataCmd {    static final Logger LOGGER = LoggerFactory.getLogger(UpdateNodeMetadataCmd.class);    @Autowired    NodesApi nodesApi;    public void execute(String nodeId) throws IOException {        Map<String, Object> properties = new HashMap<>();        properties.put("cm:title", "UPDATED title");        properties.put("cm:description", "UPDATED description");        Node node = updateNode(nodeId, "newname.txt", properties, null, null);    }    /**     * Update a node (such as file/folder).     *     * @param nodeId the id of the node that we want to update metadata for.     * @param newName a new name for the node (sets cm:name)     * @param properties the properties we want to update and their new values     * @param aspectNames a list of aspect names to set the node, not that it needs to include all aspects as it will overwrite     * @param permissionsBody permissions to set on the node     * @return updated Node object     */    private Node updateNode(String nodeId,                            String newName,                            Map<String, Object> properties,                            List<String> aspectNames,                            PermissionsBody permissionsBody) {        List<String> include = null;        List<String> fields = null;        NodeBodyUpdate nodeBodyUpdate = new NodeBodyUpdate();        nodeBodyUpdate.setName(newName);        nodeBodyUpdate.setProperties(properties);        nodeBodyUpdate.setAspectNames(aspectNames);        nodeBodyUpdate.setPermissions(permissionsBody);        NodeEntry result = nodesApi.updateNode(nodeId, nodeBodyUpdate, include, fields).getBody();        LOGGER.info("Updated node {}", result.getEntry());        return result.getEntry();    }}

With theupdateNode call we can update properties, aspects, and permissions for a node. Note that when updatingaspects you need to include the complete list of aspects that should be set on the node as this call overwrites. You canfetch existing aspects with thegetNodeMetadata call. If you are adding an aspect that has properties,then you can just add the properties and the aspect will be added automatically for you.

Executing this code result in this for a text file example:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar update-metadata 0492460b-6269-4ca1-9668-0d934d2f33702021-04-29 16:27:42.303  INFO 20246 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.185 seconds (JVM running for 3.683)2021-04-29 16:27:42.306  INFO 20246 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: update-metadata2021-04-29 16:27:42.308  INFO 20246 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 0492460b-6269-4ca1-9668-0d934d2f33702021-04-29 16:27:43.089  INFO 20246 --- [           main] o.a.t.restapi.UpdateNodeMetadataCmd      : Updated node class Node {    id: 0492460b-6269-4ca1-9668-0d934d2f3370    name: newname.txt    nodeType: acme:document    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-04-29T15:27:42.528Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-28T12:02:33.143Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: 8fa4e27d-35aa-411d-8bbe-831b6ed0c445    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: text/plain        mimeTypeName: Plain Text        sizeInBytes: 30        encoding: ISO-8859-1    }    aspectNames: [rn:renditioned, cm:versionable, cm:titled, cm:auditable, acme:securityClassified, cm:author, cm:thumbnailModification]    properties: {cm:title=UPDATED title, cm:versionType=MAJOR, acme:documentId=DOC-001, cm:versionLabel=3.0, acme:securityClassification=Company Confidential, cm:lastThumbnailModification=[doclib:1619613896873, pdf:1619701086215], cm:description=UPDATED description}    allowableOperations: null    path: null    permissions: null    definition: null}

We can see the updated name and properties in the returned node object.

Add aspects to a folder or file

To add aspects to a node, use theNodesApi.updateNodemethod. The way you do this is described in theupdate metadata for a node section. Note that youonly need to add aspects to a node when they are so called “marker” aspects without properties.

More info about this ReST API endpoint

Remove aspects from a folder or file

To remove aspects from a node, use theNodesApi.updateNodemethod. The way you do this is described in theupdate metadata for a node section.

Removing an aspect from a node is similar to how you add a “marker” aspect. You first get the list of aspects currentlyapplied to the node. Then you remove the aspect from the list. And finally you use an update node call with the updatedaspect list.

More info about this ReST API endpoint

Get and Set permissions for a folder or file

To manage permissions for a node, use theNodesApi.updateNodemethod.

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

In the following example we show how a node can be updated with new permissions for a group and a user.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.ArrayList;import java.util.List;@Componentpublic class SetNodePermissionsMetadataCmd {    static final Logger LOGGER = LoggerFactory.getLogger(SetNodePermissionsMetadataCmd.class);    @Autowired    NodesApi nodesApi;    public void execute(String nodeId) throws IOException {        // First get current permissions        PermissionsInfo currentPermissions = getNodePermissions(nodeId);        // Update with permissions for a user and a group        // Add current permissions first, it will overwrite so we need to add what's already set        PermissionsBody permissionsBody = new PermissionsBody();        permissionsBody.setIsInheritanceEnabled(true);        permissionsBody.setLocallySet(currentPermissions.getLocallySet());        PermissionElement engineeringGroupPermission = new PermissionElement();        engineeringGroupPermission.setName("Collaborator");        engineeringGroupPermission.setAuthorityId("GROUP_engineering");        engineeringGroupPermission.setAccessStatus(PermissionElement.AccessStatusEnum.ALLOWED);        permissionsBody.addLocallySetItem(engineeringGroupPermission);        PermissionElement testUserPermission = new PermissionElement();        testUserPermission.setName("Contributor");        testUserPermission.setAuthorityId("tester");        testUserPermission.setAccessStatus(PermissionElement.AccessStatusEnum.ALLOWED);        permissionsBody.addLocallySetItem(testUserPermission);        // Update permissions for node        Node node = updateNodePermissions(nodeId, permissionsBody);    }    /**     * Get node permissions.     *     * @param nodeId the id of the node that we want to get permissions for.     * @return updated Node object     */    private PermissionsInfo getNodePermissions(String nodeId) {        String relativePath = null;        List<String> fields = null;        List<String> include = new ArrayList<>();        include.add("permissions");        NodeEntry result = nodesApi.getNode(nodeId, include, relativePath, fields).getBody();        LOGGER.info("Got node including permissions {}", result.getEntry());        return result.getEntry().getPermissions();    }    /**     * Update node permissions.     *     * @param nodeId the id of the node that we want to update permissions for.     * @param permissionsBody permissions to set on the node     * @return updated Node object     */    private Node updateNodePermissions(String nodeId,                                       PermissionsBody permissionsBody) {        List<String> include = new ArrayList<>();        include.add("permissions");        List<String> fields = null;        NodeBodyUpdate nodeBodyUpdate = new NodeBodyUpdate();        nodeBodyUpdate.setPermissions(permissionsBody);        NodeEntry result = nodesApi.updateNode(nodeId, nodeBodyUpdate, include, fields).getBody();        LOGGER.info("Updated node permissions {}", result.getEntry());        return result.getEntry();    }}

Note that you have to first get the currently set permissions before you set the new ones. This is because theupdate call will overwrite permissions already set. So we use thegetNodeMetadata call to getalready set node permissions.

Executing this code result in this for a text file example:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar update-permissions 0492460b-6269-4ca1-9668-0d934d2f33702021-04-30 09:32:02.206  INFO 21515 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.4 seconds (JVM running for 3.957)2021-04-30 09:32:02.208  INFO 21515 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: update-permissions2021-04-30 09:32:02.210  INFO 21515 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 0492460b-6269-4ca1-9668-0d934d2f33702021-04-30 09:32:02.509  INFO 21515 --- [           main] o.a.t.r.SetNodePermissionsMetadataCmd    : Got node including permissions class Node {    id: 0492460b-6269-4ca1-9668-0d934d2f3370    name: newname.txt    nodeType: acme:document    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-04-29T15:27:42.528Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-28T12:02:33.143Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: 8fa4e27d-35aa-411d-8bbe-831b6ed0c445    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: text/plain        mimeTypeName: Plain Text        sizeInBytes: 30        encoding: ISO-8859-1    }    aspectNames: [rn:renditioned, cm:versionable, cm:titled, cm:auditable, acme:securityClassified, cm:author, cm:thumbnailModification]    properties: {cm:title=UPDATED title, cm:versionType=MAJOR, acme:documentId=DOC-001, cm:versionLabel=3.0, acme:securityClassification=Company Confidential, cm:lastThumbnailModification=[doclib:1619613896873, pdf:1619701086215], cm:description=UPDATED description}    allowableOperations: null    path: null    permissions: class PermissionsInfo {        isInheritanceEnabled: true        inherited: [class PermissionElement {            authorityId: GROUP_EVERYONE            name: Consumer            accessStatus: ALLOWED        }, class PermissionElement {            authorityId: guest            name: Consumer            accessStatus: ALLOWED        }]        locallySet: null        settable: [Contributor, Collaborator, Coordinator, Editor, Consumer]    }    definition: null}2021-04-30 09:32:02.708  INFO 21515 --- [           main] o.a.t.r.SetNodePermissionsMetadataCmd    : Updated node permissions class Node {    id: 0492460b-6269-4ca1-9668-0d934d2f3370    name: newname.txt    nodeType: acme:document    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-04-30T08:32:02.635Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-28T12:02:33.143Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: 8fa4e27d-35aa-411d-8bbe-831b6ed0c445    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: text/plain        mimeTypeName: Plain Text        sizeInBytes: 30        encoding: ISO-8859-1    }    aspectNames: [rn:renditioned, cm:versionable, cm:titled, cm:auditable, acme:securityClassified, cm:author, cm:thumbnailModification]    properties: {cm:title=UPDATED title, cm:versionType=MAJOR, acme:documentId=DOC-001, cm:versionLabel=3.0, acme:securityClassification=Company Confidential, cm:lastThumbnailModification=[doclib:1619613896873, pdf:1619701086215], cm:description=UPDATED description}    allowableOperations: null    path: null    permissions: class PermissionsInfo {        isInheritanceEnabled: true        inherited: [class PermissionElement {            authorityId: guest            name: Consumer            accessStatus: ALLOWED        }, class PermissionElement {            authorityId: GROUP_EVERYONE            name: Consumer            accessStatus: ALLOWED        }]        locallySet: [class PermissionElement {            authorityId: GROUP_engineering            name: Collaborator            accessStatus: ALLOWED        }, class PermissionElement {            authorityId: tester            name: Contributor            accessStatus: ALLOWED        }]        settable: [Contributor, Collaborator, Coordinator, Editor, Consumer]    }    definition: null}

We can see that before the permission update there were no locally set permissions for the node, onlyinherited. Afterthe update we see also thelocallySet returned with the newly set permissions. Note that for the permission informationto be returned with each call we have to addpermissions to theinclude parameter.

Working with relationships between folders/files

To manage relationships (referred to as associations) between nodes use theNodesApiand the following methods:

MethodDescription
listNodeChildrenList primary parent-child associations, seelist folder content
createSecondaryChildAssociationCreate secondary parent-child association
deleteSecondaryChildAssociationDelete secondary parent-child association
listSecondaryChildrenList secondary parent-child associations
createAssociationCreate peer-2-peer association
deleteAssociationDelete peer-2-peer association(s)
listSourceAssociationsList source peer-2-peer associations
listTargetAssociationsList target peer-2-peer associations

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

Assuming we have deployed theFDK content modelwith secondary parent-child and peer-2-peer association types, then the following code examples shows how to create thosetypes of associations (it also shows how to upload files, create folder, create node of different type):

Note. this code assumes the following two files exists in current directory:somepicture.png andsometext.txt.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.*;import org.apache.commons.io.FileUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.File;import java.io.IOException;import java.util.*;@Componentpublic class ManageAssociationsCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ManageAssociationsCmd.class);    @Autowired    NodesApi nodesApi;    private Boolean autoRename = true;    private Boolean majorVersion = true;    private Boolean versioningEnabled = true;    private String updateComment = null;    private String updatedName = null;    private List<String> include = null;    private List<String> fields = null;    private List<String> orderBy = null;    private Integer skipCount = 0;    private Integer maxItems = 100;    private String where = null;    private Boolean includeSource = false;    public void execute() throws IOException {        // List all folders and files (primary parent-child associations) in /Company Home/Data Dictionary        NodeChildAssociationPagingList primaryChildAssociations =                listPrimaryChildAssociations("-root-", "/Data Dictionary");        // Create gadget folder, gadget image, and gadget review        Node gadgetFolderNode = createFolder("My Gadgets", "");        Node gadgetPictureNode = uploadFile(gadgetFolderNode.getId(), "gadget-picture.png", "somepicture.png");        Node gadgetReviewNode = uploadFile(gadgetFolderNode.getId(), "gadget-review.txt", "sometext.txt");        // Create the Gadget company node        Map<String, Object> properties = new HashMap<>();        properties.put("fdk:email", "info@coolgadgets.com");        properties.put("fdk:url","www.coolgadgets.com");        properties.put("fdk:city","London");        Node companyNode = createNode(gadgetFolderNode.getId(), "Cool Gadgets Inc","fdk:company", properties);        // Create a gadget node with associations using the FDK content model        List<ChildAssociationBody> secondaryParentChildAssociations = new ArrayList<>();        ChildAssociationBody childAssoc = new ChildAssociationBody();        childAssoc.assocType("fdk:images");        childAssoc.setChildId(gadgetPictureNode.getId());        secondaryParentChildAssociations.add(childAssoc);        List<AssociationBody> peer2peerAssociations = new ArrayList<>();        AssociationBody peer2peerAssoc = new AssociationBody();        peer2peerAssoc.assocType("fdk:reviews");        peer2peerAssoc.setTargetId(gadgetReviewNode.getId());        peer2peerAssociations.add(peer2peerAssoc);        AssociationBody peer2peerAssoc2 = new AssociationBody();        peer2peerAssoc2.assocType("fdk:company");        peer2peerAssoc2.setTargetId(companyNode.getId());        peer2peerAssociations.add(peer2peerAssoc2);        Node gadgetNode = createNodeWithAssociations(                gadgetFolderNode.getId(),"My Gadget", "fdk:gadget",                secondaryParentChildAssociations, peer2peerAssociations);        // List secondary parent-child associations for a node        NodeChildAssociationPagingList secondaryAssoc = listSecondaryChildAssociations(gadgetNode.getId());        // List peer-2-peer associations for a node        NodeAssociationPagingList targetAssoc = listPeer2PeerAssociations(gadgetNode.getId());    }    /**     * List primary parent-child associations. Basically list folder contents.     *     * @param rootNodeId         the id of the folder node that is the root. If relativeFolderPath is null, then content in this folder will be listed. Besides node ID the aliases -my-, -root- and -shared- are also supported.     * @param relativeFolderPath path relative rootNodeId, if this is not null, then the content of this folder will be listed     * @return a list of child node objects contained in the folder, or null if not found     */    private NodeChildAssociationPagingList listPrimaryChildAssociations(String rootNodeId, String relativeFolderPath) {        LOGGER.info("Listing primary child associations for folder {}{}", rootNodeId, relativeFolderPath);        NodeChildAssociationPagingList result = nodesApi.listNodeChildren(rootNodeId, skipCount, maxItems, orderBy, where, include,                relativeFolderPath, includeSource, fields).getBody().getList();        for (NodeChildAssociationEntry childNodeAssoc: result.getEntries()) {            LOGGER.info("Found primary child [name=" + childNodeAssoc.getEntry().getName() + "]");        }        return result;    }    /**     * List secondary parent-child associations.     *     * @param nodeId         the node to list assoc for     * @return a list of child node objects contained in the node, or null if not found     */    private NodeChildAssociationPagingList listSecondaryChildAssociations(String nodeId) {        LOGGER.info("Listing secondary child associations for node {}", nodeId);        NodeChildAssociationPagingList result = nodesApi.listSecondaryChildren(                nodeId, where, include, skipCount, maxItems, includeSource, fields).getBody().getList();        for (NodeChildAssociationEntry childNodeAssoc: result.getEntries()) {            LOGGER.info("Found secondary child [name=" + childNodeAssoc.getEntry().getName() + "]");        }        return result;    }    /**     * List peer-2-peer associations.     *     * @param nodeId         the node to list assoc for     * @return a list of assoc objects associated with the node     */    private NodeAssociationPagingList listPeer2PeerAssociations(String nodeId) {        LOGGER.info("Listing peer-2-peer associations for node {}", nodeId);        NodeAssociationPagingList result = nodesApi.listTargetAssociations(                nodeId, where, include, fields).getBody().getList();        for (NodeAssociationEntry targetAssoc: result.getEntries()) {            LOGGER.info("Found target [name=" + targetAssoc.getEntry().getName() + "]");        }        return result;    }    /**     * Create a node with associations.     *     * @param parentNodeId the parent node id     * @param nodeName     the name of the node     * @param nodeType     the type of the node     * @param secondaryParentChildAssociations a list of secondary parent-child associations that should be set up     * @param peer2peerAssociations a list of peer-2-peer associations that should be set up     * @return a node object for the newly created node, contains the ID,     * such as e859588c-ae81-4c5e-a3b6-4c6109b6c905     */    private Node createNodeWithAssociations(            String parentNodeId,            String nodeName,            String nodeType,            List<ChildAssociationBody> secondaryParentChildAssociations,            List<AssociationBody> peer2peerAssociations) {        NodeBodyCreate nodeBodyCreate = new NodeBodyCreate();        nodeBodyCreate.setName(nodeName);        nodeBodyCreate.setNodeType(nodeType);        nodeBodyCreate.setSecondaryChildren(secondaryParentChildAssociations);        nodeBodyCreate.setTargets(peer2peerAssociations);        Node node = nodesApi.createNode(parentNodeId, nodeBodyCreate, autoRename, majorVersion, versioningEnabled,                include, fields).getBody().getEntry();        LOGGER.info("Created new node with associations: {}", node);        return node;    }    /**     * Make the remote call to create a folder in the repository, if it does not exist.     *     * @param folderName         the name of the folder     * @param relativeFolderPath path relative to /Company Home     * @return a node object for the newly created node, contains the ID,     * such as e859588c-ae81-4c5e-a3b6-4c6109b6c905     */    private Node createFolder(String folderName,                              String relativeFolderPath) {        String nodeId = "-root-";        NodeBodyCreate nodeBodyCreate = new NodeBodyCreate();        nodeBodyCreate.setName(folderName);        nodeBodyCreate.setNodeType("cm:folder");        nodeBodyCreate.setRelativePath(relativeFolderPath);        Node folderNode = nodesApi.createNode(nodeId, nodeBodyCreate, autoRename, majorVersion, versioningEnabled,                include, fields).getBody().getEntry();        LOGGER.info("Created new folder: {}", folderNode);        return folderNode;    }    /**     * Create a node     *     * @param parentNodeId  the node id for parent folder     * @param nodeName      the name of the node     * @param nodeType      the type of the node     * @return a node object for the newly created node, contains the ID,     * such as e859588c-ae81-4c5e-a3b6-4c6109b6c905     */    private Node createNode(String parentNodeId,                            String nodeName,                            String nodeType,                            Map<String, Object> properties) {        NodeBodyCreate nodeBodyCreate = new NodeBodyCreate();        nodeBodyCreate.setName(nodeName);        nodeBodyCreate.setNodeType(nodeType);        nodeBodyCreate.setProperties(properties);        Node node = nodesApi.createNode(                parentNodeId, nodeBodyCreate, autoRename, majorVersion, versioningEnabled, include, fields).getBody().getEntry();        LOGGER.info("Created new node: {}", node);        return node;    }    /**     * Upload a file from disk     */    private Node uploadFile(String folderId, String fileName, String filePath) {        // Create the file node metadata        NodeBodyCreate nodeBodyCreate = new NodeBodyCreate();        nodeBodyCreate.setName(fileName);        nodeBodyCreate.setNodeType("cm:content");        Node fileNode = nodesApi.createNode(                folderId, nodeBodyCreate, autoRename, majorVersion, versioningEnabled, include, fields).getBody().getEntry();        // Get the file bytes        File someFile = new File(filePath);        byte[] fileData = null;        try {            fileData = FileUtils.readFileToByteArray(someFile);        } catch (IOException e) {            e.printStackTrace();        }        // Add the file node content        Node updatedFileNode = nodesApi.updateNodeContent(fileNode.getId(),                fileData, majorVersion, updateComment, updatedName, include, fields).getBody().getEntry();        LOGGER.info("Created file with content: {}", updatedFileNode.toString());        return updatedFileNode;    }}

Executing the above code will result in logs such as follows:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar manage-associations                                    2021-04-30 16:26:22.678  INFO 22647 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 2.93 seconds (JVM running for 3.402)2021-04-30 16:26:22.680  INFO 22647 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: manage-associations2021-04-30 16:26:22.681  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Listing primary child associations for folder -root-/Data Dictionary2021-04-30 16:26:23.071  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Email Templates]2021-04-30 16:26:23.071  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Imap Configs]2021-04-30 16:26:23.071  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Messages]2021-04-30 16:26:23.071  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Models]2021-04-30 16:26:23.071  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Node Templates]2021-04-30 16:26:23.071  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Presentation Templates]2021-04-30 16:26:23.071  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Rendering Actions Space]2021-04-30 16:26:23.071  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Replication Actions Space]2021-04-30 16:26:23.071  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=RSS Templates]2021-04-30 16:26:23.071  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Saved Searches]2021-04-30 16:26:23.072  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Scheduled Actions]2021-04-30 16:26:23.072  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Scripts]2021-04-30 16:26:23.072  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Smart Folder Downloads]2021-04-30 16:26:23.072  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Smart Folder Templates]2021-04-30 16:26:23.072  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Solr Facets Space]2021-04-30 16:26:23.072  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Space Templates]2021-04-30 16:26:23.072  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Transfers]2021-04-30 16:26:23.072  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Web Client Extension]2021-04-30 16:26:23.072  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Web Scripts]2021-04-30 16:26:23.072  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Web Scripts Extensions]2021-04-30 16:26:23.072  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found primary child [name=Workflow Definitions]2021-04-30 16:26:23.184  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Created new folder: class Node {    id: e6bacba5-0dba-40af-afa0-ff25e10a18bb    name: My Gadgets    nodeType: cm:folder    isFolder: true    isFile: false    isLocked: false    modifiedAt: 2021-04-30T15:26:23.129Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-30T15:26:23.129Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: e439190c-3fe0-48a1-8a9a-374fbc54b570    isLink: null    isFavorite: null    content: null    aspectNames: [cm:auditable]    properties: null    allowableOperations: null    path: null    permissions: null    definition: null}2021-04-30 16:26:23.482  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Created file with content: class Node {    id: b9bf8f12-269f-46a3-97a8-16900644a7d6    name: gadget-picture.png    nodeType: cm:content    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-04-30T15:26:23.404Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-30T15:26:23.218Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: e6bacba5-0dba-40af-afa0-ff25e10a18bb    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: image/png        mimeTypeName: PNG Image        sizeInBytes: 14799        encoding: UTF-8    }    aspectNames: [cm:versionable, cm:auditable]    properties: {cm:versionLabel=2.0, cm:versionType=MAJOR}    allowableOperations: null    path: null    permissions: null    definition: null}2021-04-30 16:26:23.716  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Created file with content: class Node {    id: bb35fdd6-f2f3-44e4-84c9-30e48efaf3d5    name: gadget-review.txt    nodeType: cm:content    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-04-30T15:26:23.644Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-30T15:26:23.507Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: e6bacba5-0dba-40af-afa0-ff25e10a18bb    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: text/plain        mimeTypeName: Plain Text        sizeInBytes: 30        encoding: ISO-8859-1    }    aspectNames: [cm:versionable, cm:auditable]    properties: {cm:versionLabel=2.0, cm:versionType=MAJOR}    allowableOperations: null    path: null    permissions: null    definition: null}2021-04-30 16:26:23.918  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Created new node: class Node {    id: 01c5e298-a6c2-4b5c-81e0-195172626e22    name: Cool Gadgets Inc    nodeType: fdk:company    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-04-30T15:26:23.772Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-30T15:26:23.772Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: e6bacba5-0dba-40af-afa0-ff25e10a18bb    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: application/octet-stream        mimeTypeName: Binary File (Octet Stream)        sizeInBytes: 0        encoding: UTF-8    }    aspectNames: [cm:versionable, cm:auditable]    properties: {fdk:email=info@coolgadgets.com, fdk:url=www.coolgadgets.com, cm:versionType=MAJOR, cm:versionLabel=1.0, fdk:city=London}    allowableOperations: null    path: null    permissions: null    definition: null}2021-04-30 16:26:24.133  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Created new node with associations: class Node {    id: c5f329e8-7872-4e92-abe1-e7dd5f5f48ba    name: My Gadget    nodeType: fdk:gadget    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-04-30T15:26:23.950Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-30T15:26:23.950Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: e6bacba5-0dba-40af-afa0-ff25e10a18bb    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: application/octet-stream        mimeTypeName: Binary File (Octet Stream)        sizeInBytes: 0        encoding: UTF-8    }    aspectNames: [cm:versionable, cm:auditable]    properties: {cm:versionLabel=1.0, cm:versionType=MAJOR}    allowableOperations: null    path: null    permissions: null    definition: null}2021-04-30 16:26:24.134  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Listing secondary child associations for node c5f329e8-7872-4e92-abe1-e7dd5f5f48ba2021-04-30 16:26:24.156  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found secondary child [name=gadget-picture.png]2021-04-30 16:26:24.157  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Listing peer-2-peer associations for node c5f329e8-7872-4e92-abe1-e7dd5f5f48ba2021-04-30 16:26:24.239  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found target [name=gadget-review.txt]2021-04-30 16:26:24.239  INFO 22647 --- [           main] o.a.t.restapi.ManageAssociationsCmd      : Found target [name=Cool Gadgets Inc]

To create associations for existing nodes use thecreateSecondaryChildAssociation andcreateAssociation methods.

Manage comments for a folder or file

To manage comments for a node, use theCommentsApiand the following methods:

MethodDescription
createCommentCreate a comment for a node
deleteCommentDelete a comment for a node
listCommentsList comments for a node
updateCommentUpdate a comment for a node

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.CommentsApi;import org.alfresco.core.model.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.ArrayList;import java.util.List;@Componentpublic class ManageCommentsCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ManageCommentsCmd.class);    private Integer skipCount = 0;    private Integer maxItems = 100;    private List<String> fields = new ArrayList<>();    // Fetch only the fields we are interested in    public ManageCommentsCmd() {        fields.add("content,createdAt");    }    @Autowired    CommentsApi commentsApi;    public void execute(String nodeId) throws IOException {        Comment firstComment = createComment(nodeId, "First comment");        Comment secondComment = createComment(nodeId, "Second comment");        LOGGER.info("Listing comments: ");        CommentPagingList comments = commentsApi.listComments(nodeId, skipCount, maxItems, fields).getBody().getList();        for (CommentEntry commentEntry: comments.getEntries()) {            LOGGER.info("    {}", commentEntry.getEntry());        }    }    private Comment createComment(String nodeId, String text) {        CommentBody commentBody = new CommentBody();        commentBody.setContent(text);        Comment comment = commentsApi.createComment(nodeId, commentBody, fields).getBody().getEntry();        LOGGER.info("{}", comment);        return comment;    }}

Note the use of thefields parameter to limit the number of fields returned with each call, which saves bandwidth.

Executing the code gives a log like follows:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar manage-comments 0492460b-6269-4ca1-9668-0d934d2f33702021-05-03 18:54:48.085  INFO 26804 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.075 seconds (JVM running for 3.55)2021-05-03 18:54:48.087  INFO 26804 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: manage-comments2021-05-03 18:54:48.088  INFO 26804 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 0492460b-6269-4ca1-9668-0d934d2f33702021-05-03 18:54:48.373  INFO 26804 --- [           main] o.a.tutorial.restapi.ManageCommentsCmd   : class Comment {    id: null    title: null    content: First comment    createdBy: null    createdAt: 2021-05-03T17:54:48.224Z    edited: null    modifiedBy: null    modifiedAt: null    canEdit: null    canDelete: null}2021-05-03 18:54:48.492  INFO 26804 --- [           main] o.a.tutorial.restapi.ManageCommentsCmd   : class Comment {    id: null    title: null    content: Second comment    createdBy: null    createdAt: 2021-05-03T17:54:48.417Z    edited: null    modifiedBy: null    modifiedAt: null    canEdit: null    canDelete: null}2021-05-03 18:54:48.492  INFO 26804 --- [           main] o.a.tutorial.restapi.ManageCommentsCmd   : Listing comments: 2021-05-03 18:54:48.545  INFO 26804 --- [           main] o.a.tutorial.restapi.ManageCommentsCmd   :     class Comment {    id: null    title: null    content: Second comment    createdBy: null    createdAt: 2021-05-03T17:54:48.417Z    edited: null    modifiedBy: null    modifiedAt: null    canEdit: null    canDelete: null}2021-05-03 18:54:48.545  INFO 26804 --- [           main] o.a.tutorial.restapi.ManageCommentsCmd   :     class Comment {    id: null    title: null    content: First comment    createdBy: null    createdAt: 2021-05-03T17:54:48.224Z    edited: null    modifiedBy: null    modifiedAt: null    canEdit: null    canDelete: null}

Manage tags for a folder or file

To manage tags for a node, use theTagsApiand the following methods:

MethodDescription
createTagForNodeCreate a tag for a node
deleteTagFromNodeDelete a tag from a node
getTagGet a tag
listTagsList tags
listTagsForNodeList tags for a node
updateTagUpdate a tag

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.TagsApi;import org.alfresco.core.model.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.ArrayList;import java.util.List;@Componentpublic class ManageTagsCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ManageTagsCmd.class);    private Integer skipCount = 0;    private Integer maxItems = 100;    private List<String> fields = null;    private List<String> include = new ArrayList<>();    // Include an extra field with tag count    public ManageTagsCmd() {        include.add("count");    }    @Autowired    TagsApi tagsApi;    public void execute(String nodeId) throws IOException {        Tag firstTag = createTag(nodeId, "tag-one");        Tag secondTag = createTag(nodeId, "tag-two");        LOGGER.info("Listing tags for the whole repository: ");        TagPagingList repoTags = tagsApi.listTags(skipCount, maxItems, fields, include).getBody().getList();        for (TagEntry repoTagEntry: repoTags.getEntries()) {            LOGGER.info("    {} count: {}", repoTagEntry.getEntry().getTag(), repoTagEntry.getEntry().getCount());        }        LOGGER.info("Listing tags for node: {}", nodeId);        TagPagingList nodeTags = tagsApi.listTagsForNode(nodeId, skipCount, maxItems, fields).getBody().getList();        for (TagEntry nodeTagEntry: nodeTags.getEntries()) {            LOGGER.info("    {}", nodeTagEntry.getEntry());        }    }    private Tag createTag(String nodeId, String text) {        TagBody tagBody = new TagBody();        tagBody.setTag(text);        Tag tag = tagsApi.createTagForNode(nodeId, tagBody, fields).getBody().getEntry();        LOGGER.info("Created Tag {}", tag);        return tag;    }}

Executing the code gives a log like follows:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar manage-tags 0492460b-6269-4ca1-9668-0d934d2f33702021-05-04 09:56:25.846  INFO 27655 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 2.884 seconds (JVM running for 3.333)2021-05-04 09:56:25.848  INFO 27655 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: manage-tags2021-05-04 09:56:25.849  INFO 27655 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 0492460b-6269-4ca1-9668-0d934d2f33702021-05-04 09:56:26.073  INFO 27655 --- [           main] o.a.tutorial.restapi.ManageTagsCmd       : Created Tag class Tag {    id: a6da6c4d-cb6b-41b5-a010-7188459dd3cb    tag: tag-one    count: null}2021-05-04 09:56:26.175  INFO 27655 --- [           main] o.a.tutorial.restapi.ManageTagsCmd       : Created Tag class Tag {    id: 9a9044c9-3787-44ca-bd92-c6797c9a82ae    tag: tag-two    count: null}2021-05-04 09:56:26.175  INFO 27655 --- [           main] o.a.tutorial.restapi.ManageTagsCmd       : Listing tags for the whole repository: 2021-05-04 09:56:26.288  INFO 27655 --- [           main] o.a.tutorial.restapi.ManageTagsCmd       :     activiti count: 32021-05-04 09:56:26.288  INFO 27655 --- [           main] o.a.tutorial.restapi.ManageTagsCmd       :     aps count: 12021-05-04 09:56:26.288  INFO 27655 --- [           main] o.a.tutorial.restapi.ManageTagsCmd       :     tag-one count: null2021-05-04 09:56:26.288  INFO 27655 --- [           main] o.a.tutorial.restapi.ManageTagsCmd       :     tag-two count: null2021-05-04 09:56:26.288  INFO 27655 --- [           main] o.a.tutorial.restapi.ManageTagsCmd       :     white-paper count: 22021-05-04 09:56:26.288  INFO 27655 --- [           main] o.a.tutorial.restapi.ManageTagsCmd       : Listing tags for node: 0492460b-6269-4ca1-9668-0d934d2f33702021-05-04 09:56:26.310  INFO 27655 --- [           main] o.a.tutorial.restapi.ManageTagsCmd       :     class Tag {    id: a6da6c4d-cb6b-41b5-a010-7188459dd3cb    tag: tag-one    count: null}2021-05-04 09:56:26.310  INFO 27655 --- [           main] o.a.tutorial.restapi.ManageTagsCmd       :     class Tag {    id: 9a9044c9-3787-44ca-bd92-c6797c9a82ae    tag: tag-two    count: null}

Note that the tag count are not available directly after you have created the tag. It has to be indexed first.

Copy folders and files

To copy a node, such as a file or folder, use thecopyNode method of theNodesApi.

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.Node;import org.alfresco.core.model.NodeBodyCopy;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.ArrayList;import java.util.List;@Componentpublic class CopyNodeCmd {    static final Logger LOGGER = LoggerFactory.getLogger(CopyNodeCmd.class);    @Autowired    NodesApi nodesApi;    public void execute(String nodeId, String parentFolderNodeId) throws IOException {        List<String> include = new ArrayList<>();        List<String> fields = null;        include.add("path"); // add extra path property in response so we can see location of node        Node node = nodesApi.getNode(nodeId, include, null, fields).getBody().getEntry();        LOGGER.info("Got node we want to copy ID: {} Parent: {} Location: {}",                node.getId(), node.getParentId(), node.getPath().getName());        NodeBodyCopy nodeBodyCopy = new NodeBodyCopy();        nodeBodyCopy.setTargetParentId(parentFolderNodeId);        Node copiedNode = nodesApi.copyNode(nodeId, nodeBodyCopy, include, fields).getBody().getEntry();        LOGGER.info("Copied node ID: {} Parent: {} Location: {}",                copiedNode.getId(), copiedNode.getParentId(), copiedNode.getPath().getName());    }}

Executing this code would give the following result, passing in node to copy and target folder node:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar copy-node 0492460b-6269-4ca1-9668-0d934d2f3370 7f041db0-fdb6-4185-b921-2fb9ed3814802021-05-04 10:52:16.741  INFO 28353 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.667 seconds (JVM running for 4.218)2021-05-04 10:52:16.743  INFO 28353 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: copy-node2021-05-04 10:52:16.745  INFO 28353 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 0492460b-6269-4ca1-9668-0d934d2f33702021-05-04 10:52:16.745  INFO 28353 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: 7f041db0-fdb6-4185-b921-2fb9ed3814802021-05-04 10:52:16.974  INFO 28353 --- [           main] o.alfresco.tutorial.restapi.CopyNodeCmd  : Got node we want to copy ID: 0492460b-6269-4ca1-9668-0d934d2f3370 Parent: 8fa4e27d-35aa-411d-8bbe-831b6ed0c445 Location: /Company Home/Guest Home2021-05-04 10:52:17.366  INFO 28353 --- [           main] o.alfresco.tutorial.restapi.CopyNodeCmd  : Copied node ID: fe955da0-c4e5-42d3-972f-697424b546b1 Parent: 7f041db0-fdb6-4185-b921-2fb9ed381480 Location: /Company Home/Imap Attachments

Note the new node ID for the copy in the response.

Note that we set theinclude parameter topath so the location of the node is returned.The following extra information is returned:

Location: class PathInfo {    elements: [class PathElement {        id: e439190c-3fe0-48a1-8a9a-374fbc54b570        name: Company Home        nodeType: cm:folder        aspectNames: [cm:titled, cm:auditable, app:uifacets]    }, class PathElement {        id: 7f041db0-fdb6-4185-b921-2fb9ed381480        name: Imap Attachments        nodeType: cm:folder        aspectNames: [cm:titled, cm:auditable, app:uifacets]    }]    name: /Company Home/Imap Attachments    isComplete: true}

Move folders and files

To copy a node, such as a file or folder, use themoveNode method of theNodesApi.

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.Node;import org.alfresco.core.model.NodeBodyMove;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.ArrayList;import java.util.List;@Componentpublic class MoveNodeCmd {    static final Logger LOGGER = LoggerFactory.getLogger(MoveNodeCmd.class);    @Autowired    NodesApi nodesApi;    public void execute(String nodeId, String parentFolderNodeId) throws IOException {        List<String> include = new ArrayList<>();        List<String> fields = null;        include.add("path"); // add extra path property in response so we can see location of node        Node node = nodesApi.getNode(nodeId, include, null, fields).getBody().getEntry();        LOGGER.info("Got node before move ID: {} Parent: {} Location: {}",                node.getId(), node.getParentId(), node.getPath().getName());        NodeBodyMove nodeBodyMove = new NodeBodyMove();        nodeBodyMove.setTargetParentId(parentFolderNodeId);        Node movedNode = nodesApi.moveNode(nodeId, nodeBodyMove, include, fields).getBody().getEntry();        LOGGER.info("Moved node ID: {} Parent: {} Location: {}",                movedNode.getId(), movedNode.getParentId(), movedNode.getPath().getName());    }}

Executing this code would give the following result, passing in node to copy and target folder node:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar move-node d11d6970-c5c4-4edd-9971-593a23b9344f 7f041db0-fdb6-4185-b921-2fb9ed3814802021-05-04 10:45:47.080  INFO 28288 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.103 seconds (JVM running for 3.568)2021-05-04 10:45:47.081  INFO 28288 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: move-node2021-05-04 10:45:47.082  INFO 28288 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: d11d6970-c5c4-4edd-9971-593a23b9344f2021-05-04 10:45:47.082  INFO 28288 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: 7f041db0-fdb6-4185-b921-2fb9ed3814802021-05-04 10:45:47.276  INFO 28288 --- [           main] o.alfresco.tutorial.restapi.MoveNodeCmd  : Got node before move ID: d11d6970-c5c4-4edd-9971-593a23b9344f Parent: 8fa4e27d-35aa-411d-8bbe-831b6ed0c445 Location: /Company Home/Guest Home2021-05-04 10:45:47.458  INFO 28288 --- [           main] o.alfresco.tutorial.restapi.MoveNodeCmd  : Moved node ID: d11d6970-c5c4-4edd-9971-593a23b9344f Parent: 7f041db0-fdb6-4185-b921-2fb9ed381480 Location: /Company Home/Imap Attachments

Note that the node ID in the response is the same as passed in node ID, it is just the location of the node thathas changed when moving it.

Note that we set theinclude parameter topath so the location of the node is returned.The following extra information is returned:

Location: class PathInfo {    elements: [class PathElement {        id: e439190c-3fe0-48a1-8a9a-374fbc54b570        name: Company Home        nodeType: cm:folder        aspectNames: [cm:titled, cm:auditable, app:uifacets]    }, class PathElement {        id: 7f041db0-fdb6-4185-b921-2fb9ed381480        name: Imap Attachments        nodeType: cm:folder        aspectNames: [cm:titled, cm:auditable, app:uifacets]    }]    name: /Company Home/Imap Attachments    isComplete: true}

Lock a file for editing

To lock a file for editing, use thelockNode method of theNodesApi.Use theunlockNode method when you are finished editing the node.

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.Node;import org.alfresco.core.model.NodeBodyLock;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class LockNodeCmd {    static final Logger LOGGER = LoggerFactory.getLogger(LockNodeCmd.class);    @Autowired    NodesApi nodesApi;    public void execute(String nodeId) throws IOException {        List<String> include = null;        List<String> fields = null;        Node node = nodesApi.getNode(nodeId, include, null, fields).getBody().getEntry();        LOGGER.info("Got node we want to lock ID: {} Is locked ?: {}", node.getId(), node.isIsLocked());        if (!node.isIsLocked()) {            // Lock the file with exclusive lock            NodeBodyLock nodeBodyLock = new NodeBodyLock();            Node lockedNode = nodesApi.lockNode(nodeId, nodeBodyLock, include, fields).getBody().getEntry();            LOGGER.info("Locked node: {}", lockedNode);            // Do the work on the file            // Unlock the file            Node unLockedNode = nodesApi.unlockNode(nodeId, include, fields).getBody().getEntry();            LOGGER.info("Unlocked node: {}", unLockedNode);        }    }}

Executing this code would give the following result, passing in node to lock:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar lock-node 0492460b-6269-4ca1-9668-0d934d2f3370                                 2021-05-04 11:12:51.070  INFO 28630 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.722 seconds (JVM running for 4.523)2021-05-04 11:12:51.072  INFO 28630 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: lock-node2021-05-04 11:12:51.074  INFO 28630 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 0492460b-6269-4ca1-9668-0d934d2f33702021-05-04 11:12:51.285  INFO 28630 --- [           main] o.alfresco.tutorial.restapi.LockNodeCmd  : Got node we want to lock ID: 0492460b-6269-4ca1-9668-0d934d2f3370 Is locked ?: false2021-05-04 11:12:51.671  INFO 28630 --- [           main] o.alfresco.tutorial.restapi.LockNodeCmd  : Locked node: class Node {    id: 0492460b-6269-4ca1-9668-0d934d2f3370    name: newname.txt    nodeType: acme:document    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-05-04T08:56:26.135Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-28T12:02:33.143Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: 8fa4e27d-35aa-411d-8bbe-831b6ed0c445    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: text/plain        mimeTypeName: Plain Text        sizeInBytes: 30        encoding: ISO-8859-1    }    aspectNames: [rn:renditioned, cm:versionable, acme:securityClassified, cm:taggable, cm:thumbnailModification, fm:discussable, cm:titled, cm:lockable, cm:auditable, fm:commentsRollup, cm:author]    properties: {cm:lockType=WRITE_LOCK, cm:title=UPDATED title, cm:lockOwner={id=admin, displayName=Administrator}, cm:versionType=MAJOR, acme:documentId=DOC-001, cm:versionLabel=3.0, cm:lockLifetime=PERSISTENT, fm:commentCount=2, acme:securityClassification=Company Confidential, cm:lastThumbnailModification=[doclib:1619613896873, pdf:1619701086215], cm:description=UPDATED description, cm:taggable=[a6da6c4d-cb6b-41b5-a010-7188459dd3cb, 9a9044c9-3787-44ca-bd92-c6797c9a82ae]}    allowableOperations: null    path: null    permissions: null    definition: null}2021-05-04 11:12:51.743  INFO 28630 --- [           main] o.alfresco.tutorial.restapi.LockNodeCmd  : Unlocked node: class Node {    id: 0492460b-6269-4ca1-9668-0d934d2f3370    name: newname.txt    nodeType: acme:document    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-05-04T08:56:26.135Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-28T12:02:33.143Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: 8fa4e27d-35aa-411d-8bbe-831b6ed0c445    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: text/plain        mimeTypeName: Plain Text        sizeInBytes: 30        encoding: ISO-8859-1    }    aspectNames: [rn:renditioned, cm:versionable, acme:securityClassified, cm:taggable, cm:thumbnailModification, fm:discussable, cm:titled, cm:auditable, fm:commentsRollup, cm:author]    properties: {cm:title=UPDATED title, cm:versionType=MAJOR, acme:documentId=DOC-001, cm:versionLabel=3.0, fm:commentCount=2, acme:securityClassification=Company Confidential, cm:lastThumbnailModification=[doclib:1619613896873, pdf:1619701086215], cm:description=UPDATED description, cm:taggable=[a6da6c4d-cb6b-41b5-a010-7188459dd3cb, 9a9044c9-3787-44ca-bd92-c6797c9a82ae]}    allowableOperations: null    path: null    permissions: null    definition: null}

Note that thelockNode call response contains some extra parameters with lock information, such ascm:lockType=WRITE_LOCK andcm:lockOwner={id=admin, displayName=Administrator}.

Create a link to a file

To create a link to a file, use thecreateNode method of theNodesApiand create a node of the typeapp:filelink.

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.model.Node;import org.alfresco.core.model.NodeBodyCreate;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.*;@Componentpublic class LinkFileCmd {    static final Logger LOGGER = LoggerFactory.getLogger(LinkFileCmd.class);    @Autowired    NodesApi nodesApi;    public void execute(String parentFolderNodeId, String linkToNodeId) throws IOException {        Map<String, String> linkProps = new HashMap<>();        linkProps.put("cm:destination", linkToNodeId); // Link points to this file node        NodeBodyCreate nodeBodyCreate = new NodeBodyCreate();        nodeBodyCreate.setName("Link to a text file");        nodeBodyCreate.setNodeType("app:filelink"); // Out-of-the-box content model type for a file link        nodeBodyCreate.setProperties(linkProps);        Boolean autoRename = true;        List<String> include = new ArrayList<>();        List<String> fields = null;        Boolean majorVersion = true;        Boolean versioningEnabled = true;        // Include the isLink property in the response so we can see if a node is a link        include.add("isLink");        Node fileLinkNode = nodesApi.createNode(parentFolderNodeId, nodeBodyCreate, autoRename, majorVersion,                versioningEnabled, include, fields).getBody().getEntry();        LOGGER.info("File link: {}", fileLinkNode);    }}

Executing this code would give the following result, passing in parent folder and node to link:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar link-file 7f041db0-fdb6-4185-b921-2fb9ed381480 48413f7a-066d-4e38-b2e6-c84ede6354932021-05-04 13:27:43.981  INFO 29404 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 4.237 seconds (JVM running for 4.904)2021-05-04 13:27:43.983  INFO 29404 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: link-file2021-05-04 13:27:43.985  INFO 29404 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 7f041db0-fdb6-4185-b921-2fb9ed3814802021-05-04 13:27:43.985  INFO 29404 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: 48413f7a-066d-4e38-b2e6-c84ede6354932021-05-04 13:27:44.329  INFO 29404 --- [           main] o.alfresco.tutorial.restapi.LinkFileCmd  : File link: class Node {    id: c4ab808f-f42b-42a8-b308-d5d82df29830    name: Link to a text file    nodeType: app:filelink    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-05-04T12:27:44.166Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-05-04T12:27:44.166Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: 7f041db0-fdb6-4185-b921-2fb9ed381480    isLink: true    isFavorite: null    content: null    aspectNames: [cm:auditable]    properties: {cm:destination=48413f7a-066d-4e38-b2e6-c84ede635493}    allowableOperations: null    path: null    permissions: null    definition: null}

Note that theinclude parameter has been populated with theisLink value, which means the response will containa value for theisLink property.

Delete a folder or file

To delete a folder or a file node, use thedeleteNode method of theNodesApi.

More info about this ReST API endpoint

import org.alfresco.core.handler.NodesApi;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Component;import java.io.IOException;@Componentpublic class DeleteNodeCmd {    static final Logger LOGGER = LoggerFactory.getLogger(DeleteNodeCmd.class);    @Autowired    NodesApi nodesApi;    public void execute(String nodeId) throws IOException {        // If true, then the node is deleted permanently, without moving to the trashcan.        // Only the owner of the node or an admin can permanently delete the node.        // default value = false        Boolean permanent = false;        ResponseEntity<Void> deletedNodeResponse = nodesApi.deleteNode(nodeId, permanent);        LOGGER.info("Deleted node response: {}", deletedNodeResponse);    }}

Executing this code would give the following result, passing in the node to delete:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar delete-node fe955da0-c4e5-42d3-972f-697424b546b1                                   2021-05-04 13:47:10.376  INFO 29542 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.639 seconds (JVM running for 4.406)2021-05-04 13:47:10.377  INFO 29542 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: delete-node2021-05-04 13:47:10.379  INFO 29542 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: fe955da0-c4e5-42d3-972f-697424b546b12021-05-04 13:47:10.787  INFO 29542 --- [           main] o.a.tutorial.restapi.DeleteNodeCmd       : Deleted node response:   <204 NO_CONTENT No Content,[cache-control:"no-cache", connection:"keep-alive", content-type:"application/json;charset=UTF-8", date:"Tue, 04 May 2021 12:47:10 GMT", expires:"Thu, 01 Jan 1970 00:00:00 GMT", pragma:"no-cache", server:"nginx/1.18.0", x-frame-options:"SAMEORIGIN"]>

List deleted folders and files (Trashcan)

To list deleted nodes, use thelistDeletedNodes method of theTrashcanApi.

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.TrashcanApi;import org.alfresco.core.model.DeletedNodeEntry;import org.alfresco.core.model.DeletedNodesPaging;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.ArrayList;import java.util.List;@Componentpublic class ListDeletedNodesCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ListDeletedNodesCmd.class);    @Autowired    TrashcanApi trashcanApi;    public void execute() throws IOException {        Integer skipCount = 0;        Integer maxItems = 100;        List<String> include = new ArrayList<>();        include.add("path");        LOGGER.info("Listing soft deleted nodes in the trashcan:");        DeletedNodesPaging deletedNodes = trashcanApi.listDeletedNodes(skipCount, maxItems, include).getBody();        for (DeletedNodeEntry deletedNodeEntry: deletedNodes.getList().getEntries()) {            LOGGER.info("    Deleted node: {}", deletedNodeEntry.getEntry());        }    }}

Executing this code would list the soft deleted nodes that exist in the so called “Trashcan”:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar list-deleted-nodes                                       2021-05-05 09:38:54.983  INFO 14986 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 4.404 seconds (JVM running for 4.861)2021-05-05 09:38:54.985  INFO 14986 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: list-deleted-nodes2021-05-05 09:38:54.986  INFO 14986 --- [           main] o.a.t.restapi.ListDeletedNodesCmd        : Listing soft deleted nodes in the trashcan:2021-05-05 09:38:55.333  INFO 14986 --- [           main] o.a.t.restapi.ListDeletedNodesCmd        :     Deleted node: class DeletedNode {    id: d32e1b4b-2ae0-48c2-9ee7-6323f8f4e96b    name: My Gadgets    nodeType: cm:folder    isFolder: true    isFile: false    isLocked: false    modifiedAt: 2021-04-30T15:46:17.334Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-04-30T15:46:16.332Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: null    isLink: null    isFavorite: null    content: null    aspectNames: null    properties: null    allowableOperations: null    path: class PathInfo {        elements: [class PathElement {            id: e439190c-3fe0-48a1-8a9a-374fbc54b570            name: Company Home            nodeType: cm:folder            aspectNames: [cm:titled, cm:auditable, app:uifacets]        }]        name: /Company Home        isComplete: true    }    permissions: null    definition: null    archivedByUser: class UserInfo {        displayName: Administrator        id: admin    }    archivedAt: 2021-05-05T08:36:11.141Z}2021-05-05 09:38:55.333  INFO 14986 --- [           main] o.a.t.restapi.ListDeletedNodesCmd        :     Deleted node: class DeletedNode {    id: fe955da0-c4e5-42d3-972f-697424b546b1    name: newname.txt    nodeType: acme:document    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-05-04T09:52:17.053Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-05-04T09:52:17.053Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: null    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: text/plain        mimeTypeName: Plain Text        sizeInBytes: 30        encoding: ISO-8859-1    }    aspectNames: null    properties: null    allowableOperations: null    path: class PathInfo {        elements: [class PathElement {            id: e439190c-3fe0-48a1-8a9a-374fbc54b570            name: Company Home            nodeType: cm:folder            aspectNames: [cm:titled, cm:auditable, app:uifacets]        }, class PathElement {            id: 7f041db0-fdb6-4185-b921-2fb9ed381480            name: Imap Attachments            nodeType: cm:folder            aspectNames: [cm:titled, cm:auditable, app:uifacets]        }]        name: /Company Home/Imap Attachments        isComplete: true    }    permissions: null    definition: null    archivedByUser: class UserInfo {        displayName: Administrator        id: admin    }    archivedAt: 2021-05-04T12:47:10.524Z}

Note the extra properties at the end that tells you when the node was soft deleted and by who (i.e.archivedAt andarchivedByUser). Also, by setting theinclude parameter topath we get information about where the node was locatedbefore it was deleted (i.e.path.name)

Restore deleted folders and files (Trashcan)

To list deleted nodes, use therestoreDeletedNode method of theTrashcanApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.TrashcanApi;import org.alfresco.core.model.DeletedNodeBodyRestore;import org.alfresco.core.model.NodeEntry;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class RestoreDeletedNodeCmd {    static final Logger LOGGER = LoggerFactory.getLogger(RestoreDeletedNodeCmd.class);    @Autowired    TrashcanApi trashcanApi;    public void execute(String nodeId, String restoreFolderId) throws IOException {        List<String> fields = null;        // POST body need to ne supplied with target folder ID        DeletedNodeBodyRestore deletedNodeBodyRestore = new DeletedNodeBodyRestore();        deletedNodeBodyRestore.setTargetParentId(restoreFolderId);        deletedNodeBodyRestore.setAssocType("cm:contains");        NodeEntry restoredNode = trashcanApi.restoreDeletedNode(nodeId, fields, deletedNodeBodyRestore).getBody();        LOGGER.info("Restored node: {}", restoredNode.getEntry());    }}

Executing this code would restore a node with passed in ID. The location folder ID is also passed in:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar restore-deleted-node b717304b-1c07-400b-b8a8-3268ea79c49f 7f041db0-fdb6-4185-b921-2fb9ed3814802021-05-05 09:46:19.805  INFO 15098 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.033 seconds (JVM running for 3.498)2021-05-05 09:46:19.807  INFO 15098 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: restore-deleted-node2021-05-05 09:46:19.808  INFO 15098 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: b717304b-1c07-400b-b8a8-3268ea79c49f2021-05-05 09:46:19.808  INFO 15098 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: 7f041db0-fdb6-4185-b921-2fb9ed3814802021-05-05 09:46:20.436  INFO 15098 --- [           main] o.a.t.restapi.RestoreDeletedNodeCmd      : Restored node: class Node {    id: b717304b-1c07-400b-b8a8-3268ea79c49f    name: newname.txt    nodeType: acme:document    isFolder: false    isFile: true    isLocked: false    modifiedAt: 2021-05-04T09:19:49.903Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-05-04T09:19:49.903Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: 7f041db0-fdb6-4185-b921-2fb9ed381480    isLink: null    isFavorite: null    content: class ContentInfo {        mimeType: text/plain        mimeTypeName: Plain Text        sizeInBytes: 30        encoding: ISO-8859-1    }    aspectNames: [rn:renditioned, cm:versionable, cm:titled, cm:auditable, acme:securityClassified, cm:taggable, cm:author, cm:thumbnailModification]    properties: {cm:title=UPDATED title, cm:versionType=MAJOR, acme:documentId=DOC-001, cm:versionLabel=1.0, acme:securityClassification=Company Confidential, cm:lastThumbnailModification=[doclib:1620120715749], cm:description=UPDATED description, cm:taggable=[a6da6c4d-cb6b-41b5-a010-7188459dd3cb, 9a9044c9-3787-44ca-bd92-c6797c9a82ae]}    allowableOperations: null    path: null    permissions: null    definition: null}

=== Managing Sites ===

The following sections walk through how to use the Java ReST API wrapper services when managing Alfresco Share sites.

Create a site

To create an Alfresco Share site in the repository use thecreateSite method of theSitesApi,which is the main API used to create and manage sites.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.SitesApi;import org.alfresco.core.model.Site;import org.alfresco.core.model.SiteBodyCreate;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class CreateSite {    static final Logger LOGGER = LoggerFactory.getLogger(CreateSite.class);    private List<String> fields = null;    // Flag to indicate whether the Share-specific (surf) configuration files for the site should not be created    // Default = false    Boolean skipConfiguration = null;    // Flag to indicate whether the site should not be added to the user's site favorites    // Default = false    Boolean skipAddToFavorites = null;    @Autowired    SitesApi sitesApi;    public void execute(String siteId) throws IOException {        SiteBodyCreate siteBodyCreate = new SiteBodyCreate();        siteBodyCreate.setId(siteId);        siteBodyCreate.setTitle("title-" + siteId);        siteBodyCreate.setDescription("description-" + siteId);        siteBodyCreate.setVisibility(SiteBodyCreate.VisibilityEnum.PUBLIC);        Site site = sitesApi.createSite(siteBodyCreate, skipConfiguration, skipAddToFavorites, fields).getBody().getEntry();        LOGGER.info("Created site: {}", site);    }}

List site containers

For more information about how to list site containers, such as Document Library, for a site seeadd content to site.

Add content to a site

Adding content to a site uses the same API calls as are used to create folders and upload files elsewhere in the Repository.Seecreate folder andupload file for more information.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

The tricky bit is to figure out how to add content to the so called “Document Library” of a site. We can figure out theNode ID for the Document Library by using thelistSiteContainers method of theSitesApi:

import org.alfresco.core.handler.NodesApi;import org.alfresco.core.handler.SitesApi;import org.alfresco.core.model.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class AddSiteContentCmd {    static final Logger LOGGER = LoggerFactory.getLogger(AddSiteContentCmd.class);    Integer skipCount = 0;    Integer maxItems = 100;    private List<String> fields = null;    private List<String> include = null;    private Boolean autoRename = true;    private Boolean majorVersion = true;    private Boolean versioningEnabled = true;    @Autowired    SitesApi sitesApi;    @Autowired    NodesApi nodesApi;    public void execute(String siteId) throws IOException {        // First get the Node ID for the Document Library        String docLibNodeId = null;        SiteContainerPaging siteContainerPaging = sitesApi.listSiteContainers(siteId, skipCount, maxItems, fields).getBody();        LOGGER.info("Listing site containers [{}]: ", siteId);        for (SiteContainerEntry siteContainerEntry: siteContainerPaging.getList().getEntries()) {            SiteContainer siteContainer = siteContainerEntry.getEntry();            LOGGER.info("  Site container: {}", siteContainer);            if (siteContainer.getFolderId().equalsIgnoreCase("DocumentLibrary")) {                docLibNodeId = siteContainer.getId();            }        }        if (docLibNodeId != null) {            // Create a folder in the document library            createFolder(docLibNodeId, "White papers");        } else {            LOGGER.info("Document library not found in site {}", siteId);        }    }    /**     * Make the remote call to create a folder in the repository, if it does not exist.     *     * @param parentFolderId the node ID for the site container     * @param folderName         the name of the folder     * @return a node object for the newly created node, contains the ID,     * such as e859588c-ae81-4c5e-a3b6-4c6109b6c905     */    private Node createFolder(String parentFolderId,                              String folderName) {        NodeBodyCreate nodeBodyCreate = new NodeBodyCreate();        nodeBodyCreate.setName(folderName);        nodeBodyCreate.setNodeType("cm:folder");        Node folderNode = nodesApi.createNode(parentFolderId, nodeBodyCreate, autoRename, majorVersion, versioningEnabled,                include, fields).getBody().getEntry();        LOGGER.info("Created new folder in DocLib: {}", folderNode);        return folderNode;    }}

Executing this code will create a folder in the passed in site’s document library:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar add-site-content test2021-05-05 10:43:34.208  INFO 16095 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.019 seconds (JVM running for 3.46)2021-05-05 10:43:34.210  INFO 16095 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: add-site-content2021-05-05 10:43:34.211  INFO 16095 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: test2021-05-05 10:43:34.390  INFO 16095 --- [           main] o.a.tutorial.restapi.AddSiteContentCmd   : Listing site containers [test]: 2021-05-05 10:43:34.391  INFO 16095 --- [           main] o.a.tutorial.restapi.AddSiteContentCmd   :   Site container: class SiteContainer {    id: 605e085c-92ae-4a53-b902-99c7d215f475    folderId: documentLibrary}2021-05-05 10:43:34.833  INFO 16095 --- [           main] o.a.tutorial.restapi.AddSiteContentCmd   : Created new folder in DocLib: class Node {    id: 6e157336-068a-4384-bc29-e4e1ca09cc6c    name: White papers    nodeType: cm:folder    isFolder: true    isFile: false    isLocked: false    modifiedAt: 2021-05-05T09:43:34.660Z    modifiedByUser: class UserInfo {        displayName: Administrator        id: admin    }    createdAt: 2021-05-05T09:43:34.660Z    createdByUser: class UserInfo {        displayName: Administrator        id: admin    }    parentId: 605e085c-92ae-4a53-b902-99c7d215f475    isLink: null    isFavorite: null    content: null    aspectNames: [cm:auditable]    properties: null    allowableOperations: null    path: null    permissions: null    definition: null}

Adding members to a site

Adding members to a site uses thecreateSiteMembership method of theSitesApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.SitesApi;import org.alfresco.core.model.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;import static org.alfresco.core.model.SiteMembershipBodyCreate.RoleEnum.SITECOLLABORATOR;@Componentpublic class AddSiteMembersCmd {    static final Logger LOGGER = LoggerFactory.getLogger(AddSiteMembersCmd.class);    private List<String> fields = null;    @Autowired    SitesApi sitesApi;    public void execute(String siteId, String personId) throws IOException {        SiteMembershipBodyCreate siteMembershipBodyCreate = new SiteMembershipBodyCreate();        siteMembershipBodyCreate.setId(personId);        siteMembershipBodyCreate.setRole(SITECOLLABORATOR);        SiteMemberEntry siteMemberEntry = sitesApi.createSiteMembership(siteId, siteMembershipBodyCreate, fields).getBody();        LOGGER.info("Created site membership {}", siteMemberEntry);    }}

Executing this code will add a user with passed in ID with roleSite Collaborator to site with passed in ID:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar add-site-member test test2021-05-05 13:21:31.290  INFO 17933 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 2.923 seconds (JVM running for 3.377)2021-05-05 13:21:31.291  INFO 17933 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: add-site-member2021-05-05 13:21:31.292  INFO 17933 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: test2021-05-05 13:21:31.293  INFO 17933 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: test2021-05-05 13:21:31.697  INFO 17933 --- [           main] o.a.tutorial.restapi.AddSiteMembersCmd   : Created site membership class SiteMemberEntry {    entry: class SiteMember {        id: test        person: class Person {            id: test            firstName: Test            lastName: User            displayName: Test User            description: null            avatarId: null            email: test@example.com            skypeId: null            googleId: null            instantMessageId: null            jobTitle: null            location: null            company: class Company {                organization: null                address1: null                address2: null                address3: null                postcode: null                telephone: null                fax: null                email: null            }            mobile: null            telephone: null            statusUpdatedAt: null            userStatus: null            enabled: true            emailNotificationsEnabled: true            aspectNames: null            properties: null            capabilities: class Capabilities {                isAdmin: false                isGuest: false                isMutable: true            }        }        role: SiteCollaborator        isMemberOfGroup: false    }}

=== Managing People and Groups ===

The following sections walk through how to use the Java ReST API wrapper services when managing users and groups. Notethat these are usually managed via a directory server (LDAP/Active Directory).

List people (users)

Listing people uses thelistPeople method of thePeopleApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.PeopleApi;import org.alfresco.core.model.PersonEntry;import org.alfresco.core.model.PersonPaging;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class ListPeopleCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ListPeopleCmd.class);    @Autowired    PeopleApi peopleApi;    public void execute() throws IOException {        Integer skipCount = 0;        Integer maxItems = 100;        List<String> orderBy = null;        List<String> include = null;        List<String> fields = null;        LOGGER.info("Listing people in the repository");        PersonPaging people = peopleApi.listPeople(skipCount, maxItems, orderBy, include, fields).getBody();        for (PersonEntry personEntry: people.getList().getEntries()) {            LOGGER.info("  {} ({})", personEntry.getEntry().getDisplayName(), personEntry.getEntry().getId());        }    }}

Executing this code will list all users in the repository (note, if connected to LDAP this could be a lot of users…):

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar list-people2021-05-05 13:42:15.547  INFO 18327 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.426 seconds (JVM running for 3.96)2021-05-05 13:42:15.549  INFO 18327 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: list-people2021-05-05 13:42:15.550  INFO 18327 --- [           main] o.a.tutorial.restapi.ListPeopleCmd       : Listing people in the repository2021-05-05 13:42:15.879  INFO 18327 --- [           main] o.a.tutorial.restapi.ListPeopleCmd       :   Alice Beecher (abeecher)2021-05-05 13:42:15.880  INFO 18327 --- [           main] o.a.tutorial.restapi.ListPeopleCmd       :   Administrator (admin)2021-05-05 13:42:15.880  INFO 18327 --- [           main] o.a.tutorial.restapi.ListPeopleCmd       :   Guest (guest)2021-05-05 13:42:15.880  INFO 18327 --- [           main] o.a.tutorial.restapi.ListPeopleCmd       :   Mike Jackson (mjackson)2021-05-05 13:42:15.880  INFO 18327 --- [           main] o.a.tutorial.restapi.ListPeopleCmd       :   Test User (test)

Create a person

Creating a person uses thecreatePerson method of thePeopleApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.PeopleApi;import org.alfresco.core.model.PersonBodyCreate;import org.alfresco.core.model.PersonEntry;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class CreatePersonCmd {    static final Logger LOGGER = LoggerFactory.getLogger(CreatePersonCmd.class);    @Autowired    PeopleApi peopleApi;    public void execute(String username, String pwd, String firstname, String lastname, String email) throws IOException {        List<String> fields = null;        PersonBodyCreate personBodyCreate = new PersonBodyCreate();        personBodyCreate.setId(username);        personBodyCreate.setPassword(pwd);        personBodyCreate.setFirstName(firstname);        personBodyCreate.setLastName(lastname);        personBodyCreate.setEmail(email);        PersonEntry person = peopleApi.createPerson(personBodyCreate, fields).getBody();        LOGGER.info("Created person  {}", person);    }}

Executing this code will add a user passed in username, pwd, first name, last name and email:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar create-person martin 1234 Martin Bergljung martin@example.com2021-05-05 15:49:25.198  INFO 22389 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.928 seconds (JVM running for 4.427)2021-05-05 15:49:25.200  INFO 22389 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: create-person2021-05-05 15:49:25.201  INFO 22389 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: martin2021-05-05 15:49:25.201  INFO 22389 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: 12342021-05-05 15:49:25.201  INFO 22389 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[3]: Martin2021-05-05 15:49:25.201  INFO 22389 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[4]: Bergljung2021-05-05 15:49:25.201  INFO 22389 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[5]: martin@example.com2021-05-05 15:49:25.830  INFO 22389 --- [           main] o.a.tutorial.restapi.CreatePersonCmd     : Created person  class PersonEntry {    entry: class Person {        id: martin        firstName: Martin        lastName: Bergljung        displayName: Martin Bergljung        description: null        avatarId: null        email: martin@example.com        skypeId: null        googleId: null        instantMessageId: null        jobTitle: null        location: null        company: class Company {            organization: null            address1: null            address2: null            address3: null            postcode: null            telephone: null            fax: null            email: null        }        mobile: null        telephone: null        statusUpdatedAt: null        userStatus: null        enabled: true        emailNotificationsEnabled: true        aspectNames: null        properties: null        capabilities: class Capabilities {            isAdmin: false            isGuest: false            isMutable: true        }    }}

Get person metadata

Getting metadata for a person involves a number of API calls:

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.PeopleApi;import org.alfresco.core.handler.PreferencesApi;import org.alfresco.core.model.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class GetPersonMetadataCmd {    static final Logger LOGGER = LoggerFactory.getLogger(GetPersonMetadataCmd.class);    @Autowired    PeopleApi peopleApi;    @Autowired    PreferencesApi preferencesApi;    public void execute(String personId) throws IOException {        Integer skipCount = 0;        Integer maxItems = 100;        List<String> fields = null;        PersonEntry person = peopleApi.getPerson(personId, fields).getBody();        LOGGER.info("Got person metadata {}", person);        PreferencePaging preferencePaging = preferencesApi.listPreferences(personId, skipCount, maxItems, fields).getBody();        LOGGER.info("Got person preferences:");        for (PreferenceEntry preferenceEntry: preferencePaging.getList().getEntries()) {            LOGGER.info("  preference: {}", preferenceEntry.getEntry());        }    }}

Executing this code will list the metadata for the user including any preferences. In the following example we list metadatafor the out-of-the-box userabeecher:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar get-person-metadata abeecher2021-05-05 16:06:50.550  INFO 22610 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.396 seconds (JVM running for 3.893)2021-05-05 16:06:50.552  INFO 22610 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: get-person-metadata2021-05-05 16:06:50.553  INFO 22610 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: abeecher2021-05-05 16:06:50.787  INFO 22610 --- [           main] o.a.t.restapi.GetPersonMetadataCmd       : Got person metadata class PersonEntry {    entry: class Person {        id: abeecher        firstName: Alice        lastName: Beecher        displayName: Alice Beecher        description: Alice is a demo user for the sample Alfresco Team site.        avatarId: 198500fc-1e99-4f5f-8926-248cea433366        email: abeecher@example.com        skypeId: abeecher        googleId: null        instantMessageId: null        jobTitle: Graphic Designer        location: Tilbury, UK        company: class Company {            organization: Moresby, Garland and Wedge            address1: 200 Butterwick Street            address2: Tilbury            address3: UK            postcode: ALF1 SAM1            telephone: null            fax: null            email: null        }        mobile: 0112211001100        telephone: 0112211001100        statusUpdatedAt: 2011-02-15T20:20:13.432Z        userStatus: Helping to design the look and feel of the new web site        enabled: false        emailNotificationsEnabled: true        aspectNames: null        properties: null        capabilities: class Capabilities {            isAdmin: false            isGuest: false            isMutable: true        }    }}2021-05-05 16:06:50.849  INFO 22610 --- [           main] o.a.t.restapi.GetPersonMetadataCmd       : Got person preferences:2021-05-05 16:06:50.849  INFO 22610 --- [           main] o.a.t.restapi.GetPersonMetadataCmd       :   preference: class Preference {    id: org.alfresco.share.documentList.showFolders    value: true}2021-05-05 16:06:50.849  INFO 22610 --- [           main] o.a.t.restapi.GetPersonMetadataCmd       :   preference: class Preference {    id: org.alfresco.share.documentList.simpleView    value: false}2021-05-05 16:06:50.849  INFO 22610 --- [           main] o.a.t.restapi.GetPersonMetadataCmd       :   preference: class Preference {    id: org.alfresco.share.documentList.sortField    value: cm:name}2021-05-05 16:06:50.849  INFO 22610 --- [           main] o.a.t.restapi.GetPersonMetadataCmd       :   preference: class Preference {    id: org.alfresco.share.documents.favourites    value: workspace://SpacesStore/7c7bca1d-b65d-4444-9378-805b459fb74d,workspace://SpacesStore/b2f21ddd-0b0e-449f-bea9-a0be73e7d67b,workspace://SpacesStore/2cf35860-6705-42c3-b123-c4d6b39997b4,workspace://SpacesStore/7d90c94c-fcf7-4f79-9273-bd1352bbb612,workspace://SpacesStore/05dedd34-9d9d-48d9-9af6-c81b555541c9}2021-05-05 16:06:50.850  INFO 22610 --- [           main] o.a.t.restapi.GetPersonMetadataCmd       :   preference: class Preference {    id: org.alfresco.share.sites.favourites.test    value: true}2021-05-05 16:06:50.850  INFO 22610 --- [           main] o.a.t.restapi.GetPersonMetadataCmd       :   preference: class Preference {    id: org.alfresco.share.sites.recent._0    value: swsdp}2021-05-05 16:06:50.850  INFO 22610 --- [           main] o.a.t.restapi.GetPersonMetadataCmd       :   preference: class Preference {    id: org.alfresco.share.twisters.collapsed    value: DocumentPermissions,DocumentWorkflows,DocumentLinks,DocumentActions}

Update a person

Updating metadata for a person involves these two API calls:

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.PeopleApi;import org.alfresco.core.model.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class UpdatePersonMetadataCmd {    static final Logger LOGGER = LoggerFactory.getLogger(UpdatePersonMetadataCmd.class);    @Autowired    PeopleApi peopleApi;    public void execute(String personId) throws IOException {        List<String> fields = null;        PersonBodyUpdate personBodyUpdate = new PersonBodyUpdate();        // Mandatory fields during an update        personBodyUpdate.setFirstName("Martin");        personBodyUpdate.setLastName("Bergljung");        personBodyUpdate.setEmail("martin@example.com");        personBodyUpdate.setEmailNotificationsEnabled(true);        personBodyUpdate.setOldPassword("1234");        personBodyUpdate.setPassword("1234");        personBodyUpdate.setEnabled(true);        // Other fields        personBodyUpdate.setJobTitle("Techie");        Company company = new Company();        company.setAddress1("Alfresco way 1");        company.setOrganization("Alfresco Org");        company.setTelephone("12345678");        personBodyUpdate.setCompany(company);        PersonEntry person = peopleApi.updatePerson(personId, personBodyUpdate, fields).getBody();        LOGGER.info("Updated person metadata {}", person);    }}

Executing this code will update the usermartin with some new company information, there are a number of fields thatare mandatory that you need to set, so might be best to read them first and then set them:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar update-person-metadata martin2021-05-06 09:16:41.833  INFO 24158 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.151 seconds (JVM running for 3.596)2021-05-06 09:16:41.835  INFO 24158 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: update-person-metadata2021-05-06 09:16:41.837  INFO 24158 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: martin2021-05-06 09:16:42.111  INFO 24158 --- [           main] o.a.t.restapi.UpdatePersonMetadataCmd    : Updated person metadata class PersonEntry {    entry: class Person {        id: martin        firstName: Martin        lastName: Bergljung        displayName: Martin Bergljung        description: null        avatarId: null        email: martin@example.com        skypeId: null        googleId: null        instantMessageId: null        jobTitle: Techie        location: null        company: class Company {            organization: Alfresco Org            address1: Alfresco way 1            address2: null            address3: null            postcode: null            telephone: 12345678            fax: null            email: null        }        mobile: null        telephone: null        statusUpdatedAt: null        userStatus: null        enabled: true        emailNotificationsEnabled: true        aspectNames: null        properties: null        capabilities: class Capabilities {            isAdmin: false            isGuest: false            isMutable: true        }    }}

Request password reset for a person

Requesting a password reset for a person (user) in the repository involves these two API calls:

More info about this ReST API endpoint

import org.alfresco.core.handler.PeopleApi;import org.alfresco.core.model.ClientBody;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpEntity;import org.springframework.stereotype.Component;import java.io.IOException;@Componentpublic class RequestPwdResetCmd {    static final Logger LOGGER = LoggerFactory.getLogger(RequestPwdResetCmd.class);    @Autowired    PeopleApi peopleApi;    public void execute(String personId) throws IOException {        ClientBody clientBody = new ClientBody();        clientBody.setClient("share"); // Alfresco Share UI client        HttpEntity<Void> result = peopleApi.requestPasswordReset(personId, clientBody);        LOGGER.info("Password reset request sent for {} result {}", personId, result);    }}

Executing this code will request a password request for usermartin, an email will be sent to the user assuming thepassword request should be via the Alfresco Share UI:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar request-pwd-reset martin     2021-05-06 09:30:38.440  INFO 24356 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.438 seconds (JVM running for 3.939)2021-05-06 09:30:38.442  INFO 24356 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: request-pwd-reset2021-05-06 09:30:38.443  INFO 24356 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: martin2021-05-06 09:30:39.726  INFO 24356 --- [           main] o.a.tutorial.restapi.RequestPwdResetCmd  : Password reset request sent for martin result <202 ACCEPTED Accepted,[cache-control:"no-cache", connection:"keep-alive", content-length:"0", content-type:"application/json;charset=UTF-8", date:"Thu, 06 May 2021 08:30:39 GMT", expires:"Thu, 01 Jan 1970 00:00:00 GMT", pragma:"no-cache", server:"nginx/1.18.0", x-frame-options:"SAMEORIGIN"]>

List groups a person is a member of

Listing groups that a person is a member of uses thelistGroupMembershipsForPerson method of theGroupsApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.GroupsApi;import org.alfresco.core.model.GroupEntry;import org.alfresco.core.model.GroupPaging;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class ListPersonGroupMembershipsCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ListPersonGroupMembershipsCmd.class);    @Autowired    GroupsApi groupsApi;    public void execute(String personId) throws IOException {        Integer skipCount = 0;        Integer maxItems = 100;        String where = null;        List<String> orderBy = null;        List<String> include = null;        List<String> fields = null;        LOGGER.info("Listing group memberships for person {}", personId);        GroupPaging groups = groupsApi.listGroupMembershipsForPerson(                personId, skipCount, maxItems, orderBy, include, where, fields).getBody();        for (GroupEntry groupEntry: groups.getList().getEntries()) {            LOGGER.info("  {}", groupEntry.getEntry().getDisplayName());        }    }}

Executing this code will list the group memberships for passed in username. In this example we list group memberships fortwo of the out-of-the-box usersabeecher andadmin:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar list-person-group-memberships abeecher2021-05-06 09:42:50.643  INFO 24597 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.63 seconds (JVM running for 4.106)2021-05-06 09:42:50.645  INFO 24597 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: list-person-group-memberships2021-05-06 09:42:50.647  INFO 24597 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: abeecher2021-05-06 09:42:50.647  INFO 24597 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    : Listing group memberships for person abeecher2021-05-06 09:42:50.821  INFO 24597 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   null2021-05-06 09:42:50.821  INFO 24597 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   site_swsdp2021-05-06 09:42:50.821  INFO 24597 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   site_swsdp_SiteCollaborator% java -jar target/rest-api-0.0.1-SNAPSHOT.jar list-person-group-memberships admin   2021-05-06 09:43:06.433  INFO 24599 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: admin2021-05-06 09:43:06.433  INFO 24599 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    : Listing group memberships for person admin2021-05-06 09:43:06.631  INFO 24599 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   ALFRESCO_ADMINISTRATORS2021-05-06 09:43:06.631  INFO 24599 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   ALFRESCO_MODEL_ADMINISTRATORS2021-05-06 09:43:06.631  INFO 24599 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   ALFRESCO_SEARCH_ADMINISTRATORS2021-05-06 09:43:06.631  INFO 24599 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   EMAIL_CONTRIBUTORS2021-05-06 09:43:06.631  INFO 24599 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   null2021-05-06 09:43:06.631  INFO 24599 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   SITE_ADMINISTRATORS2021-05-06 09:43:06.632  INFO 24599 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   site_swsdp2021-05-06 09:43:06.632  INFO 24599 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   site_swsdp_SiteManager2021-05-06 09:43:06.632  INFO 24599 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   site_test2021-05-06 09:43:06.632  INFO 24599 --- [           main] o.a.t.r.ListPersonGroupMembershipsCmd    :   site_test_SiteManager```

List groups

Listing the groups available in the repository uses thelistGroups method of theGroupsApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.GroupsApi;import org.alfresco.core.model.GroupEntry;import org.alfresco.core.model.GroupPaging;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class ListGroupsCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ListGroupsCmd.class);    @Autowired    GroupsApi groupsApi;    public void execute() throws IOException {        Integer skipCount = 0;        Integer maxItems = 100;        String where = null;        List<String> orderBy = null;        List<String> include = null;        List<String> fields = null;        LOGGER.info("Listing group in the repo:");        GroupPaging groups = groupsApi.listGroups(skipCount, maxItems, orderBy, include, where, fields).getBody();        for (GroupEntry groupEntry: groups.getList().getEntries()) {            LOGGER.info("  {}", groupEntry.getEntry().getDisplayName());        }    }}

Executing this code will list the groups available in the repository, note that this can be a lot of groups if thereare loads of Share sites and the system is connected to a directory server:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar list-groups                        2021-05-06 09:50:39.416  INFO 24665 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.637 seconds (JVM running for 4.131)2021-05-06 09:50:39.419  INFO 24665 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: list-groups2021-05-06 09:50:39.420  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       : Listing group in the repo:2021-05-06 09:50:39.807  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   Engineering2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   ALFRESCO_ADMINISTRATORS2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   ALFRESCO_MODEL_ADMINISTRATORS2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   ALFRESCO_SEARCH_ADMINISTRATORS2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   EMAIL_CONTRIBUTORS2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   SITE_ADMINISTRATORS2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   site_swsdp2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   site_swsdp_SiteCollaborator2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   site_swsdp_SiteConsumer2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   site_swsdp_SiteContributor2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   site_swsdp_SiteManager2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   site_test2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   site_test_SiteCollaborator2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   site_test_SiteConsumer2021-05-06 09:50:39.808  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   site_test_SiteContributor2021-05-06 09:50:39.809  INFO 24665 --- [           main] o.a.tutorial.restapi.ListGroupsCmd       :   site_test_SiteManager

Create a group

Creating a group uses thecreateGroup method of theGroupsApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.GroupsApi;import org.alfresco.core.model.GroupBodyCreate;import org.alfresco.core.model.GroupEntry;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class CreateGroupCmd {    static final Logger LOGGER = LoggerFactory.getLogger(CreateGroupCmd.class);    @Autowired    GroupsApi groupsApi;    public void execute(String groupId, String name) throws IOException {        List<String> fields = null;        List<String> include = null;        GroupBodyCreate groupBodyCreate = new GroupBodyCreate();        groupBodyCreate.setId(groupId);        groupBodyCreate.setDisplayName(name);        GroupEntry groupEntry = groupsApi.createGroup(groupBodyCreate, include, fields).getBody();        LOGGER.info("Created group  {}", groupEntry.getEntry());    }}

Executing this code will create a group, in this case we are creating an HR group:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar create-group hr "Human Resources"2021-05-06 10:25:51.906  INFO 25139 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.477 seconds (JVM running for 3.956)2021-05-06 10:25:51.908  INFO 25139 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: create-group2021-05-06 10:25:51.909  INFO 25139 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: hr2021-05-06 10:25:51.909  INFO 25139 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: Human Resources2021-05-06 10:25:52.165  INFO 25139 --- [           main] o.a.tutorial.restapi.CreateGroupCmd      : Created group  class Group {    id: GROUP_hr    displayName: Human Resources    isRoot: true    parentIds: null    zones: null}

Get group metadata

Getting metadata for a group uses thegetGroup method of theGroupsApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.GroupsApi;import org.alfresco.core.model.GroupEntry;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class GetGroupCmd {    static final Logger LOGGER = LoggerFactory.getLogger(GetGroupCmd.class);    @Autowired    GroupsApi groupsApi;    public void execute(String groupId) throws IOException {        List<String> fields = null;        List<String> include = null;        GroupEntry groupEntry = groupsApi.getGroup(groupId, include, fields).getBody();        LOGGER.info("Got group metadata  {}", groupEntry.getEntry());    }}

Executing this code will get metadata for a group, in this case we are getting metadata for a group with idhr,note that you have to prefix group ids withGROUP_:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar get-group GROUP_hr2021-05-06 10:31:37.864  INFO 25363 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.763 seconds (JVM running for 4.242)2021-05-06 10:31:37.866  INFO 25363 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: get-group2021-05-06 10:31:37.868  INFO 25363 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: GROUP_hr2021-05-06 10:31:38.025  INFO 25363 --- [           main] o.alfresco.tutorial.restapi.GetGroupCmd  : Got group metadata  class Group {    id: GROUP_hr    displayName: Human Resources    isRoot: true    parentIds: null    zones: null}

Update a group

Updating a group name uses theupdateGroup method of theGroupsApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.GroupsApi;import org.alfresco.core.model.GroupBodyUpdate;import org.alfresco.core.model.GroupEntry;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class UpdateGroupCmd {    static final Logger LOGGER = LoggerFactory.getLogger(UpdateGroupCmd.class);    @Autowired    GroupsApi groupsApi;    public void execute(String groupId, String newName) throws IOException {        List<String> fields = null;        List<String> include = null;        GroupBodyUpdate groupBodyUpdate = new GroupBodyUpdate();        groupBodyUpdate.setDisplayName(newName);        GroupEntry group = groupsApi.updateGroup(groupId, groupBodyUpdate, include, fields).getBody();        LOGGER.info("Updated group {}", group);    }}

Executing this code will update the name of the group with passed in id, in this case we are updating the name for agroup with idhr, note that you have to prefix group ids withGROUP_:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar update-group GROUP_hr "Human Resources updated"2021-05-06 12:42:41.475  INFO 26302 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.285 seconds (JVM running for 3.742)2021-05-06 12:42:41.477  INFO 26302 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: update-group2021-05-06 12:42:41.478  INFO 26302 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: GROUP_hr2021-05-06 12:42:41.478  INFO 26302 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: Human Resources updated2021-05-06 12:42:41.673  INFO 26302 --- [           main] o.a.tutorial.restapi.UpdateGroupCmd      : Updated group class GroupEntry {    entry: class Group {        id: GROUP_hr        displayName: Human Resources updated        isRoot: true        parentIds: null        zones: null    }}

List all people and groups in a group

Listing all the members of a group (i.e. people and groups) uses thelistGroupMemberships method of theGroupsApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.GroupsApi;import org.alfresco.core.model.GroupMemberEntry;import org.alfresco.core.model.GroupMemberPaging;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class ListGroupMembersCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ListGroupMembersCmd.class);    @Autowired    GroupsApi groupsApi;    public void execute(String groupId) throws IOException {        Integer skipCount = 0;        Integer maxItems = 100;        String where = null;        List<String> orderBy = null;        List<String> fields = null;        LOGGER.info("Listing members of group {}:", groupId);        GroupMemberPaging groupMembers = groupsApi.listGroupMemberships(                groupId, skipCount, maxItems, orderBy, where, fields).getBody();        for (GroupMemberEntry groupMemberEntry: groupMembers.getList().getEntries()) {            LOGGER.info("  {} ({})", groupMemberEntry.getEntry().getDisplayName(),                     groupMemberEntry.getEntry().getMemberType());        }    }}

Executing this code will list the members of passed in group id, note that you have to prefix group ids withGROUP_:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar list-group-members GROUP_engineering2021-05-06 12:55:43.231  INFO 26500 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.59 seconds (JVM running for 4.024)2021-05-06 12:55:43.233  INFO 26500 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: list-group-members2021-05-06 12:55:43.234  INFO 26500 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: GROUP_engineering2021-05-06 12:55:43.234  INFO 26500 --- [           main] o.a.t.restapi.ListGroupMembersCmd        : Listing members of group GROUP_engineering:2021-05-06 12:55:43.404  INFO 26500 --- [           main] o.a.t.restapi.ListGroupMembersCmd        :   martin (PERSON)2021-05-06 12:55:43.404  INFO 26500 --- [           main] o.a.t.restapi.ListGroupMembersCmd        :   System Architects (GROUP)

Adding people and groups to a group

Adding members to a group uses thecreateGroupMembership method of theGroupsApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.GroupsApi;import org.alfresco.core.model.GroupMemberEntry;import org.alfresco.core.model.GroupMembershipBodyCreate;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class CreateGroupMembershipCmd {    static final Logger LOGGER = LoggerFactory.getLogger(CreateGroupMembershipCmd.class);    @Autowired    GroupsApi groupsApi;    public void execute(String groupId, String memberId, String type) throws IOException {        List<String> fields = null;        GroupMembershipBodyCreate groupMembershipBodyCreate = new GroupMembershipBodyCreate();        groupMembershipBodyCreate.setId(memberId);        groupMembershipBodyCreate.setMemberType(GroupMembershipBodyCreate.MemberTypeEnum.fromValue(type));        GroupMemberEntry groupMember = groupsApi.createGroupMembership(groupId, groupMembershipBodyCreate, fields).getBody();        LOGGER.info("Added member to group {} {}", groupId, groupMember.getEntry());    }}

Executing this code will add a person, or a group, to passed in group id, note that you have to prefix group ids withGROUP_:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar create-group-membership GROUP_hr martin PERSON2021-05-06 13:54:39.062  INFO 27295 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.83 seconds (JVM running for 4.364)2021-05-06 13:54:39.064  INFO 27295 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: create-group-membership2021-05-06 13:54:39.066  INFO 27295 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: GROUP_hr2021-05-06 13:54:39.066  INFO 27295 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: martin2021-05-06 13:54:39.066  INFO 27295 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[3]: PERSON2021-05-06 13:54:39.311  INFO 27295 --- [           main] o.a.t.restapi.CreateGroupMembershipCmd   : Added member to group GROUP_hr class GroupMember {    id: martin    displayName: martin    memberType: PERSON}% java -jar target/rest-api-0.0.1-SNAPSHOT.jar create-group-membership GROUP_hr GROUP_engineering GROUP2021-05-06 13:55:23.094  INFO 27297 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.855 seconds (JVM running for 4.351)2021-05-06 13:55:23.096  INFO 27297 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: create-group-membership2021-05-06 13:55:23.097  INFO 27297 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: GROUP_hr2021-05-06 13:55:23.097  INFO 27297 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: GROUP_engineering2021-05-06 13:55:23.097  INFO 27297 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[3]: GROUP2021-05-06 13:55:23.327  INFO 27297 --- [           main] o.a.t.restapi.CreateGroupMembershipCmd   : Added member to group GROUP_hr class GroupMember {    id: GROUP_engineering    displayName: Engineering    memberType: GROUP}

Delete a person or group from a group

Deleting members of a group uses thedeleteGroupMembership method of theGroupsApi.

More info about this ReST API endpoint

import org.alfresco.core.handler.GroupsApi;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpEntity;import org.springframework.stereotype.Component;import java.io.IOException;@Componentpublic class DeleteGroupMembershipCmd {    static final Logger LOGGER = LoggerFactory.getLogger(DeleteGroupMembershipCmd.class);    @Autowired    GroupsApi groupsApi;    public void execute(String groupId, String groupMemberId) throws IOException {        HttpEntity<Void> result = groupsApi.deleteGroupMembership(groupId, groupMemberId);        LOGGER.info("Deleted group membership for group {} member {} result {}", groupId, groupMemberId, result);    }}

Executing this code will delete a person, or a group, from passed in group id, note that you have to prefix group idswithGROUP_:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar delete-group-membership GROUP_hr martin           2021-05-06 14:09:25.825  INFO 27471 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.959 seconds (JVM running for 4.516)2021-05-06 14:09:25.828  INFO 27471 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: delete-group-membership2021-05-06 14:09:25.829  INFO 27471 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: GROUP_hr2021-05-06 14:09:25.829  INFO 27471 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: martin2021-05-06 14:09:26.112  INFO 27471 --- [           main] o.a.t.restapi.DeleteGroupMembershipCmd   : Deleted group membership for group GROUP_hr member martin result <204 NO_CONTENT No Content,[cache-control:"no-cache", connection:"keep-alive", content-type:"application/json;charset=UTF-8", date:"Thu, 06 May 2021 13:09:26 GMT", expires:"Thu, 01 Jan 1970 00:00:00 GMT", pragma:"no-cache", server:"nginx/1.18.0", x-frame-options:"SAMEORIGIN"]>% java -jar target/rest-api-0.0.1-SNAPSHOT.jar delete-group-membership GROUP_hr GROUP_engineering2021-05-06 14:09:51.048  INFO 27472 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.964 seconds (JVM running for 4.493)2021-05-06 14:09:51.050  INFO 27472 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: delete-group-membership2021-05-06 14:09:51.051  INFO 27472 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: GROUP_hr2021-05-06 14:09:51.051  INFO 27472 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: GROUP_engineering2021-05-06 14:09:51.152  INFO 27472 --- [           main] o.a.t.restapi.DeleteGroupMembershipCmd   : Deleted group membership for group GROUP_hr member GROUP_engineering result <204 NO_CONTENT No Content,[cache-control:"no-cache", connection:"keep-alive", content-type:"application/json;charset=UTF-8", date:"Thu, 06 May 2021 13:09:51 GMT", expires:"Thu, 01 Jan 1970 00:00:00 GMT", pragma:"no-cache", server:"nginx/1.18.0", x-frame-options:"SAMEORIGIN"]>

Setting permissions for a group

Setting permissions for a group uses theupdateNode method of theNodesApi.For more info seeset permissions for a node.

More info about this ReST API endpoint

=== Managing Audit Applications and Logs ===

The following sections walk through how to use the Java ReST API wrapper services when managing audit applications andtheir logs.

Enable auditing and Alfresco Access audit application

See this section

List audit applications

Listing all the audit applications uses thelistAuditApps method of theAuditApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.AuditApi;import org.alfresco.core.model.AuditAppEntry;import org.alfresco.core.model.AuditAppPaging;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class ListAuditAppsCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ListAuditAppsCmd.class);    @Autowired    AuditApi auditApi;    public void execute() throws IOException {        Integer skipCount = 0;        Integer maxItems = 100;        List<String> fields = null;        LOGGER.info("Listing active audit applications in the repository:");        AuditAppPaging auditApps = auditApi.listAuditApps(skipCount, maxItems, fields).getBody();        for (AuditAppEntry auditAppEntry: auditApps.getList().getEntries()) {            LOGGER.info("  {}", auditAppEntry);        }    }}

Executing this code will list the audit applications that have been activated, if you have enabled auditing and activatedthealfresco-access audit application, then you will see the following listing of audit apps:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar list-audit-apps2021-05-07 12:48:12.434  INFO 36995 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.525 seconds (JVM running for 4.089)2021-05-07 12:48:12.436  INFO 36995 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: list-audit-apps2021-05-07 12:48:12.437  INFO 36995 --- [           main] o.a.tutorial.restapi.ListAuditAppsCmd    : Listing active audit applications in the repository:2021-05-07 12:48:12.912  INFO 36995 --- [           main] o.a.tutorial.restapi.ListAuditAppsCmd    :   class AuditAppEntry {    entry: class AuditApp {        id: tagging        name: Alfresco Tagging Service        isEnabled: true        maxEntryId: null        minEntryId: null    }}2021-05-07 12:48:12.913  INFO 36995 --- [           main] o.a.tutorial.restapi.ListAuditAppsCmd    :   class AuditAppEntry {    entry: class AuditApp {        id: alfresco-access        name: alfresco-access        isEnabled: true        maxEntryId: null        minEntryId: null    }}

Get audit application metadata

Getting the audit application metadata uses thegetAuditApp method of theAuditApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.AuditApi;import org.alfresco.core.model.AuditApp;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class GetAuditAppCmd {    static final Logger LOGGER = LoggerFactory.getLogger(GetAuditAppCmd.class);    @Autowired    AuditApi auditApi;    public void execute(String auditAppId) throws IOException {        List<String> fields = null;        List<String> include = null;        AuditApp auditApp = auditApi.getAuditApp(auditAppId, fields, include).getBody();        LOGGER.info("Got audit app metadata  {}", auditApp);    }}

Enable/Disable an audit application

Enable and disable an audit application uses theupdateAuditApp method of theAuditApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.AuditApi;import org.alfresco.core.model.AuditApp;import org.alfresco.core.model.AuditBodyUpdate;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class EnableDisableAuditAppCmd {    static final Logger LOGGER = LoggerFactory.getLogger(EnableDisableAuditAppCmd.class);    @Autowired    AuditApi auditApi;    public void execute(String auditAppId) throws IOException {        List<String> fields = null;        AuditBodyUpdate auditBodyUpdate = new AuditBodyUpdate();        auditBodyUpdate.setIsEnabled(true);        AuditApp auditApp = auditApi.updateAuditApp(auditAppId, auditBodyUpdate, fields).getBody();        LOGGER.info("Enabled audit app  {}", auditApp);    }}

List audit entries (logs) for an audit application

Listing all the audit logs for an audit application uses thelistAuditEntriesForAuditApp method of theAuditApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.AuditApi;import org.alfresco.core.model.AuditEntryEntry;import org.alfresco.core.model.AuditEntryPaging;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.ArrayList;import java.util.List;@Componentpublic class ListAuditLogsCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ListAuditLogsCmd.class);    @Autowired    AuditApi auditApi;    public void execute(String auditAppId) throws IOException {        Integer skipCount = 0;        Integer maxItems = 100;        String where = null;        List<String> fields = null;        List<String> include = new ArrayList<>();        List<String> orderBy = null;        // Include the log values        include.add("values");        // Controls if the response provides the total numbers of items in the collection.        // If not supplied then the default value is false.        Boolean omitTotalItems = true;        LOGGER.info("Listing logs for audit application {}:", auditAppId);        AuditEntryPaging auditLogs = auditApi.listAuditEntriesForAuditApp(                auditAppId, skipCount, omitTotalItems, orderBy, maxItems, where, include, fields).getBody();        for (AuditEntryEntry auditAppEntry: auditLogs.getList().getEntries()) {            String username = "N/A";            if (auditAppEntry.getEntry().getCreatedByUser() != null) {                username = auditAppEntry.getEntry().getCreatedByUser().getId();            }            String log = null;            if (auditAppEntry.getEntry().getValues().toString().length() > 60) {                log = auditAppEntry.getEntry().getValues().toString().substring(0, 60);            } else {                log = auditAppEntry.getEntry().getValues().toString();            }            LOGGER.info("  {} {} {}", auditAppEntry.getEntry().getCreatedAt(), username, log);        }    }}

Note that you have to addvalues to theinclude parameter for the logs to include all the data. Also, the audit logvalue have been truncated for readability.

Executing this code will list the audit logs for passed in audit app id. The audit log values have been trimmed:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar list-audit-logs alfresco-access2021-05-07 14:46:29.977  INFO 40544 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.493 seconds (JVM running for 3.948)2021-05-07 14:46:29.980  INFO 40544 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: list-audit-logs2021-05-07 14:46:29.981  INFO 40544 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: alfresco-access2021-05-07 14:46:29.981  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    : Listing logs for audit application alfresco-access:2021-05-07 14:46:30.376  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T11:48:12.758Z admin {/alfresco-access/login/user=admin}2021-05-07 14:46:30.376  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:30:46.256Z N/A {/alfresco-access/loginFailure/user=martin}2021-05-07 14:46:30.377  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:30:58.768Z N/A {/alfresco-access/loginFailure/user=test}2021-05-07 14:46:30.377  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:31:07.650Z admin {/alfresco-access/transaction/sub-actions=createNode updateN2021-05-07 14:46:30.379  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:31:08.087Z admin {/alfresco-access/transaction/sub-actions=createNode updateN2021-05-07 14:46:30.379  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:31:08.141Z admin {/alfresco-access/transaction/sub-actions=createNode updateN2021-05-07 14:46:30.379  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:31:08.800Z admin {/alfresco-access/transaction/sub-actions=updateContent upda2021-05-07 14:46:30.379  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:31:08.853Z admin {/alfresco-access/transaction/sub-actions=updateContent upda2021-05-07 14:46:30.380  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:31:08.961Z admin {/alfresco-access/transaction/sub-actions=updateContent upda2021-05-07 14:46:30.380  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:04.579Z admin {/alfresco-access/logout/user=admin}2021-05-07 14:46:30.381  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:10.404Z test {/alfresco-access/login/user=test}2021-05-07 14:46:30.381  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:11.261Z test {/alfresco-access/transaction/sub-actions=createNode updateN2021-05-07 14:46:30.381  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:11.316Z test {/alfresco-access/transaction/sub-actions=createNode updateN2021-05-07 14:46:30.381  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:11.371Z test {/alfresco-access/transaction/sub-actions=createNode updateN2021-05-07 14:46:30.381  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:11.436Z test {/alfresco-access/transaction/sub-actions=createNode updateN2021-05-07 14:46:30.382  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:12.075Z test {/alfresco-access/transaction/sub-actions=updateContent upda2021-05-07 14:46:30.382  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:12.101Z test {/alfresco-access/transaction/sub-actions=updateContent upda2021-05-07 14:46:30.382  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:12.124Z test {/alfresco-access/transaction/sub-actions=updateContent upda2021-05-07 14:46:30.383  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:24.764Z test {/alfresco-access/logout/user=test}2021-05-07 14:46:30.383  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:26.423Z admin {/alfresco-access/login/user=admin}2021-05-07 14:46:30.384  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:37.917Z admin {/alfresco-access/transaction/sub-actions=createNode updateN2021-05-07 14:46:30.384  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:47.013Z admin {/alfresco-access/transaction/sub-actions=createNode updateN2021-05-07 14:46:30.385  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:51.284Z admin {/alfresco-access/transaction/sub-actions=addNodeAspect crea2021-05-07 14:46:30.385  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:51.363Z admin {/alfresco-access/transaction/sub-actions=readContent addNod2021-05-07 14:46:30.385  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:51.458Z admin {/alfresco-access/transaction/sub-actions=updateNodeProperti2021-05-07 14:46:30.385  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:51.511Z admin {/alfresco-access/transaction/sub-actions=readContent, /alfr2021-05-07 14:46:30.385  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:54.271Z admin {/alfresco-access/transaction/sub-actions=addNodeAspect crea2021-05-07 14:46:30.385  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:54.343Z admin {/alfresco-access/transaction/sub-actions=updateNodeProperti2021-05-07 14:46:30.385  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:54.443Z admin {/alfresco-access/transaction/sub-actions=updateNodeProperti2021-05-07 14:46:30.385  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:32:54.468Z admin {/alfresco-access/transaction/sub-actions=readContent, /alfr2021-05-07 14:46:30.385  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:33:03.656Z admin {/alfresco-access/transaction/sub-actions=createNode updateN2021-05-07 14:46:30.385  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:33:03.784Z admin {/alfresco-access/transaction/sub-actions=readContent, /alfr2021-05-07 14:46:30.385  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:33:04.218Z admin {/alfresco-access/transaction/sub-actions=addNodeAspect, /al2021-05-07 14:46:30.386  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:33:04.264Z admin {/alfresco-access/transaction/sub-actions=readContent, /alfr2021-05-07 14:46:30.386  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:33:04.347Z admin {/alfresco-access/transaction/sub-actions=readContent, /alfr2021-05-07 14:46:30.386  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:33:04.754Z admin {/alfresco-access/transaction/sub-actions=addNodeAspect crea2021-05-07 14:46:30.386  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:33:04.806Z admin {/alfresco-access/transaction/sub-actions=addNodeAspect upda2021-05-07 14:46:30.386  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:33:04.878Z admin {/alfresco-access/transaction/sub-actions=updateNodeProperti2021-05-07 14:46:30.386  INFO 40544 --- [           main] o.a.tutorial.restapi.ListAuditLogsCmd    :   2021-05-07T13:33:04.899Z admin {/alfresco-access/transaction/sub-actions=readContent, /alfr

List audit entries (logs) for a node

Listing all the audit logs for a node uses thelistAuditEntriesForNode method of theAuditApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.AuditApi;import org.alfresco.core.model.AuditEntryEntry;import org.alfresco.core.model.AuditEntryPaging;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.ArrayList;import java.util.List;@Componentpublic class ListNodeAuditLogsCmd {    static final Logger LOGGER = LoggerFactory.getLogger(ListNodeAuditLogsCmd.class);    @Autowired    AuditApi auditApi;    public void execute(String nodeId) throws IOException {        Integer skipCount = 0;        Integer maxItems = 100;        String where = null;        List<String> fields = null;        List<String> include = new ArrayList<>();        List<String> orderBy = null;        // Include the log values        include.add("values");        LOGGER.info("Listing logs for node ID {}:", nodeId);        AuditEntryPaging auditLogs = auditApi.listAuditEntriesForNode(                nodeId, skipCount, orderBy, maxItems, where, include, fields).getBody();        for (AuditEntryEntry auditAppEntry: auditLogs.getList().getEntries()) {            String username = "N/A";            if (auditAppEntry.getEntry().getCreatedByUser() != null) {                username = auditAppEntry.getEntry().getCreatedByUser().getId();            }            String log = null;            if (auditAppEntry.getEntry().getValues().toString().length() > 60) {                log = auditAppEntry.getEntry().getValues().toString().substring(0, 60);            } else {                log = auditAppEntry.getEntry().getValues().toString();            }            LOGGER.info("  {} {} {} {}", auditAppEntry.getEntry().getId(), auditAppEntry.getEntry().getCreatedAt(),                    username, log);        }    }}

Note that you have to addvalues to theinclude parameter for the logs to include all the data. Also, the audit logvalue have been truncated for readability.

Executing this code will list the audit logs for passed in audit app id and audit entry id:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar list-audit-logs-node 37eedde2-3c78-4d25-bade-5360e22579f42021-05-10 09:27:33.714  INFO 51172 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 4.069 seconds (JVM running for 4.724)2021-05-10 09:27:33.716  INFO 51172 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: list-audit-logs-node2021-05-10 09:27:33.717  INFO 51172 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: 37eedde2-3c78-4d25-bade-5360e22579f42021-05-10 09:27:33.717  INFO 51172 --- [           main] o.a.t.restapi.ListNodeAuditLogsCmd       : Listing logs for node ID 37eedde2-3c78-4d25-bade-5360e22579f4:2021-05-10 09:41:55.396  INFO 51505 --- [           main] o.a.t.restapi.ListNodeAuditLogsCmd       :   76 2021-05-10T08:26:58.965Z admin {/alfresco-access/transaction/sub-actions=updateNodeProperti2021-05-10 09:41:55.396  INFO 51505 --- [           main] o.a.t.restapi.ListNodeAuditLogsCmd       :   77 2021-05-10T08:27:06.541Z admin {/alfresco-access/transaction/sub-actions=readContent, /alfr2021-05-10 09:41:55.396  INFO 51505 --- [           main] o.a.t.restapi.ListNodeAuditLogsCmd       :   78 2021-05-10T08:27:11.353Z admin {/alfresco-access/transaction/sub-actions=updateContent upda2021-05-10 09:41:55.396  INFO 51505 --- [           main] o.a.t.restapi.ListNodeAuditLogsCmd       :   80 2021-05-10T08:27:12.270Z admin {/alfresco-access/transaction/sub-actions=updateNodeProperti2021-05-10 09:41:55.397  INFO 51505 --- [           main] o.a.t.restapi.ListNodeAuditLogsCmd       :   81 2021-05-10T08:27:12.429Z admin {/alfresco-access/transaction/sub-actions=readContent, /alfr2021-05-10 09:41:55.397  INFO 51505 --- [           main] o.a.t.restapi.ListNodeAuditLogsCmd       :   83 2021-05-10T08:27:13.524Z admin {/alfresco-access/transaction/sub-actions=updateNodeProperti2021-05-10 09:41:55.397  INFO 51505 --- [           main] o.a.t.restapi.ListNodeAuditLogsCmd       :   84 2021-05-10T08:27:13.609Z admin {/alfresco-access/transaction/sub-actions=readContent, /alfr

Get an audit entry (log)

Getting an audit log uses thegetAuditEntry method of theAuditApi.

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.AuditApi;import org.alfresco.core.model.AuditEntryEntry;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class GetAuditLogCmd {    static final Logger LOGGER = LoggerFactory.getLogger(GetAuditLogCmd.class);    @Autowired    AuditApi auditApi;    public void execute(String auditAppId, String auditLogId) throws IOException {        List<String> fields = null;        AuditEntryEntry auditLog = auditApi.getAuditEntry(auditAppId, auditLogId, fields).getBody();        LOGGER.info("Got audit log metadata  {}", auditLog);    }}

Executing this code will list the audit logs for passed in audit app id. The audit log values have been trimmed:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar get-audit-log alfresco-access 80                     2021-05-10 09:49:57.492  INFO 51645 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.49 seconds (JVM running for 3.992)2021-05-10 09:49:57.494  INFO 51645 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: get-audit-log2021-05-10 09:49:57.496  INFO 51645 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: alfresco-access2021-05-10 09:49:57.496  INFO 51645 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: 802021-05-10 09:49:57.676  INFO 51645 --- [           main] o.a.tutorial.restapi.GetAuditLogCmd      : Got audit log metadata  class AuditEntryEntry {    entry: class AuditEntry {        id: 80        auditApplicationId: alfresco-access        createdByUser: class UserInfo {            displayName: Administrator            id: admin        }        createdAt: 2021-05-10T08:27:12.270Z        values: {          /alfresco-access/transaction/sub-actions=updateNodeProperties,           /alfresco-access/transaction/properties/from={cm:lastThumbnailModification=[pdf:1620394371183, doclib:1620394374161], {http://www.alfresco.org/model/content/1.0}modified=2021-05-10T08:27:10.986+0000},           /alfresco-access/transaction/properties/to={cm:lastThumbnailModification=[doclib:1620394374161, pdf:1620635231931], {http://www.alfresco.org/model/content/1.0}modified=2021-05-10T08:27:11.935+0000},           /alfresco-access/transaction/path=/app:company_home/app:guest_home/cm:somefileudpated.txt,           /alfresco-access/transaction/action=updateNodeProperties,           /alfresco-access/transaction/type=cm:content,           /alfresco-access/transaction/user=admin}    }}

Delete audit entries (logs) for an audit application

Deleting audit logs for an audit app uses thedeleteAuditEntriesForAuditApp method of theAuditApi.

More info about this ReST API endpoint

For a description of the common parameters, such aswhere, see thissection.

import org.alfresco.core.handler.AuditApi;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpEntity;import org.springframework.stereotype.Component;import java.io.IOException;@Componentpublic class DeleteAuditLogsForAppCmd {    static final Logger LOGGER = LoggerFactory.getLogger(DeleteAuditLogsForAppCmd.class);    @Autowired    AuditApi auditApi;    public void execute(String auditAppId) throws IOException {        // Delete all logs with ids between 1 and 79        String where = "(id BETWEEN ('1', '79'))";        HttpEntity<Void> response = auditApi.deleteAuditEntriesForAuditApp(auditAppId, where);        LOGGER.info("Deleted audit logs for app {} where {} response {}", auditAppId, where, response);    }}

Note that you have to supply awhere clause to be able to delete any audit logs.

Executing this code will delete audit logs for passed in audit app id and where clause:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar delete-audit-logs-for-app alfresco-access2021-05-10 10:05:22.248  INFO 51942 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 4.116 seconds (JVM running for 4.615)2021-05-10 10:05:22.250  INFO 51942 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: delete-audit-logs-for-app2021-05-10 10:05:22.251  INFO 51942 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: alfresco-access2021-05-10 10:05:22.357  INFO 51942 --- [           main] o.a.t.restapi.DeleteAuditLogsForAppCmd   : Deleted audit logs for app alfresco-access where (id BETWEEN ('1', '79')) response <204 NO_CONTENT No Content,[cache-control:"no-cache", connection:"keep-alive", content-type:"application/json;charset=UTF-8", date:"Mon, 10 May 2021 09:05:22 GMT", expires:"Thu, 01 Jan 1970 00:00:00 GMT", pragma:"no-cache", server:"nginx/1.18.0", x-frame-options:"SAMEORIGIN"]

Delete an audit entry (log) for an audit application

Deleting a single audit entry for an audit app uses thedeleteAuditEntry method of theAuditApi.

More info about this ReST API endpoint

import org.alfresco.core.handler.AuditApi;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpEntity;import org.springframework.stereotype.Component;import java.io.IOException;@Componentpublic class DeleteAuditLogCmd {    static final Logger LOGGER = LoggerFactory.getLogger(DeleteAuditLogCmd.class);    @Autowired    AuditApi auditApi;    public void execute(String auditAppId, String auditLogId) throws IOException {        HttpEntity<Void> response = auditApi.deleteAuditEntry(auditAppId, auditLogId);        LOGGER.info("Deleted audit log: app {} log id {} response {}", auditAppId, auditLogId, response);    }}

Executing this code will delete an audit log with passed in id for audit app with passed in id:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar delete-audit-log alfresco-access 80                      2021-05-10 10:14:54.941  INFO 52102 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.736 seconds (JVM running for 4.24)2021-05-10 10:14:54.943  INFO 52102 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: delete-audit-log2021-05-10 10:14:54.944  INFO 52102 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[1]: alfresco-access2021-05-10 10:14:54.944  INFO 52102 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[2]: 802021-05-10 10:14:55.050  INFO 52102 --- [           main] o.a.tutorial.restapi.DeleteAuditLogCmd   : Deleted audit log: app alfresco-access log id 80 response <204 NO_CONTENT No Content,[cache-control:"no-cache", connection:"keep-alive", content-type:"application/json;charset=UTF-8", date:"Mon, 10 May 2021 09:14:55 GMT", expires:"Thu, 01 Jan 1970 00:00:00 GMT", pragma:"no-cache", server:"nginx/1.18.0", x-frame-options:"SAMEORIGIN"]>

=== Searching for content ===

The following sections walk through how to use the Java ReST API wrapper services when managing audit applications andtheir logs.

Finding folders and files by a term

To find a node, such as a folder or file, by a term use thefindNodes method of theQueriesApi,which is a search API you can use when doing simple search on a term. For more complex search, such as Alfresco Full Text Search (AFTS),use theSearch API;

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.core.handler.QueriesApi;import org.alfresco.core.model.NodeEntry;import org.alfresco.core.model.NodePagingList;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class FindNodesCmd {    static final Logger LOGGER = LoggerFactory.getLogger(FindNodesCmd.class);    @Autowired    QueriesApi queriesApi;    public void execute() throws IOException {        String rootNodeId = "-root-"; // The id of the node to start the search from. Supports the aliases -my-, -root- and -shared-.        Integer skipCount = 0;        Integer maxItems = 100;        // Restrict the returned results to only those of the given node type and its sub-types        String nodeType = null;        List<String> include = null;        List<String> orderBy = null;        List<String> fields = null;        String term = "Dict*";        LOGGER.info("Searching for nodes by term: {}", term);        NodePagingList result = queriesApi.findNodes(                term, rootNodeId, skipCount, maxItems, nodeType, include, orderBy, fields).getBody().getList();        for (NodeEntry node: result.getEntries()) {            LOGGER.info("Found node [name={}][id={}]", node.getEntry().getName(), node.getEntry().getId());        }    }}

Executing this code gives the following type of result:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar find-nodes2021-05-10 13:40:47.999  INFO 54955 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.429 seconds (JVM running for 3.909)2021-05-10 13:40:48.001  INFO 54955 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: find-nodes2021-05-10 13:40:48.003  INFO 54955 --- [           main] o.a.tutorial.restapi.FindNodesCmd        : Searching for nodes by term: Dict*2021-05-10 13:40:49.143  INFO 54955 --- [           main] o.a.tutorial.restapi.FindNodesCmd        : Found node [name=Dictionary][id=b1264564-9b33-4003-bff9-58f2591cea54]2021-05-10 13:40:49.143  INFO 54955 --- [           main] o.a.tutorial.restapi.FindNodesCmd        : Found node [name=Dictionary-stuff.txt][id=6f7689af-b31e-493a-ad3a-298abcf03664]2021-05-10 13:40:49.143  INFO 54955 --- [           main] o.a.tutorial.restapi.FindNodesCmd        : Found node [name=InviteHelper.txt][id=4875faf1-6366-477a-a97b-b30d15f33808]2021-05-10 13:40:49.143  INFO 54955 --- [           main] o.a.tutorial.restapi.FindNodesCmd        : Found node [name=Data Dictionary][id=392f377c-4a0b-4ab1-8327-3034269030a5]2021-05-10 13:40:49.143  INFO 54955 --- [           main] o.a.tutorial.restapi.FindNodesCmd        : Found node [name=readme.html][id=d38b8cb0-0973-4bfd-84c5-9db4959d4715]2021-05-10 13:40:49.143  INFO 54955 --- [           main] o.a.tutorial.restapi.FindNodesCmd        : Found node [name=Project Contract.pdf][id=1a0b110f-1e09-4ca2-b367-fe25e4964a4e]2021-05-10 13:40:49.143  INFO 54955 --- [           main] o.a.tutorial.restapi.FindNodesCmd        : Found node [name=Meeting Notes 2011-02-10.doc][id=a8290263-4178-48f5-a0b0-be155a424828]2021-05-10 13:40:49.144  INFO 54955 --- [           main] o.a.tutorial.restapi.FindNodesCmd        : Found node [name=Meeting Notes 2011-02-03.doc][id=150398b3-7f82-4cf6-af63-c450ef6c5eb8]2021-05-10 13:40:49.144  INFO 54955 --- [           main] o.a.tutorial.restapi.FindNodesCmd        : Found node [name=Meeting Notes 2011-01-27.doc][id=f3bb5d08-9fd1-46da-a94a-97f20f1ef208]

Finding sites by a term

To find sites by term use thefindSites method of theQueriesApi,which is a search API you can use when doing simple search on a term. For more complex search, such as Alfresco Full Text Search (AFTS),use theSearch API;

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.QueriesApi;import org.alfresco.core.model.SiteEntry;import org.alfresco.core.model.SitePagingList;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class FindSitesCmd {    static final Logger LOGGER = LoggerFactory.getLogger(FindSitesCmd.class);    @Autowired    QueriesApi queriesApi;    public void execute() throws IOException {        Integer skipCount = 0;        Integer maxItems = 100;        List<String> orderBy = null;        List<String> fields = null;        String term = "Soft*";        LOGGER.info("Searching for sites by term: {}", term);        SitePagingList result = queriesApi.findSites(term, skipCount, maxItems, orderBy, fields).getBody().getList();        for (SiteEntry node: result.getEntries()) {            LOGGER.info("Found site [id={}][name={}]", node.getEntry().getId(), node.getEntry().getTitle());        }    }}

Executing this code gives the following type of result:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar find-sites2021-05-10 13:52:04.833  INFO 55062 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 4.107 seconds (JVM running for 4.762)2021-05-10 13:52:04.835  INFO 55062 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: find-sites2021-05-10 13:52:04.845  INFO 55062 --- [           main] o.a.tutorial.restapi.FindSitesCmd        : Searching for sites by term: Soft*2021-05-10 13:52:05.036  INFO 55062 --- [           main] o.a.tutorial.restapi.FindSitesCmd        : Found site [id=downloadable-software][name=Downloadable Software]2021-05-10 13:52:05.036  INFO 55062 --- [           main] o.a.tutorial.restapi.FindSitesCmd        : Found site [id=software-design][name=Software Design]

Finding people by a term

To find sites by term use thefindPeople method of theQueriesApi,which is a search API you can use when doing simple search on a term. For more complex search, such as Alfresco Full Text Search (AFTS),use theSearch API;

More info about this ReST API endpoint

For a description of the common parameters, such asfields, see thissection.

import org.alfresco.core.handler.QueriesApi;import org.alfresco.core.model.PersonEntry;import org.alfresco.core.model.PersonPagingList;import org.alfresco.core.model.SiteEntry;import org.alfresco.core.model.SitePagingList;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class FindPeopleCmd {    static final Logger LOGGER = LoggerFactory.getLogger(FindPeopleCmd.class);    @Autowired    QueriesApi queriesApi;    public void execute() throws IOException {        Integer skipCount = 0;        Integer maxItems = 100;        List<String> orderBy = null;        List<String> fields = null;        String term = "*mi*";        LOGGER.info("Searching for people by term: {}", term);        PersonPagingList result = queriesApi.findPeople(term, skipCount, maxItems, fields, orderBy).getBody().getList();        for (PersonEntry person: result.getEntries()) {            LOGGER.info("Found person [id={}][name={}]", person.getEntry().getId(), person.getEntry().getDisplayName());        }    }}

Executing this code gives the following type of result:

% java -jar target/rest-api-0.0.1-SNAPSHOT.jar find-people2021-05-10 14:00:38.019  INFO 55327 --- [           main] o.a.tutorial.restapi.RestApiApplication  : Started RestApiApplication in 3.568 seconds (JVM running for 4.045)2021-05-10 14:00:38.021  INFO 55327 --- [           main] o.a.tutorial.restapi.RestApiApplication  : args[0]: find-people2021-05-10 14:00:38.022  INFO 55327 --- [           main] o.a.tutorial.restapi.FindPeopleCmd       : Searching for people by term: *mi*2021-05-10 14:00:38.839  INFO 55327 --- [           main] o.a.tutorial.restapi.FindPeopleCmd       : Found person [id=admin][name=Administrator]2021-05-10 14:00:38.839  INFO 55327 --- [           main] o.a.tutorial.restapi.FindPeopleCmd       : Found person [id=mjackson][name=Mike Jackson]

Finding content by a search query

To find content based on more complex search queries, such as using Alfresco Full Text Search (AFTS), use theSearchApi,;

More info about this ReST API endpoint

For a description of the common parameters, such asinclude, see thissection.

import org.alfresco.search.handler.SearchApi;import org.alfresco.search.model.RequestQuery;import org.alfresco.search.model.ResultSetPaging;import org.alfresco.search.model.ResultSetRowEntry;import org.alfresco.search.model.SearchRequest;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Component;import java.io.IOException;import java.util.List;@Componentpublic class SearchCmd {    static final Logger LOGGER = LoggerFactory.getLogger(SearchCmd.class);    @Autowired    SearchApi searchApi;    /**     * Search in a site     *     * @param siteId the site id     * @param term the term to search for in the site     */    public void execute(String siteId, String term) throws IOException {        List<ResultSetRowEntry> result = search("(SITE:\"" + siteId + "\" AND TEXT:\"" + term + "\" )");        LOGGER.info("Search result: {}", result);    }    /**     * Search the repository for content using an Alfresco Full Text Search (AFTS) query     *     * @param aftsQuery the query statement     * @return a list of search results     */    List<ResultSetRowEntry> search(String aftsQuery) {        ResponseEntity<ResultSetPaging> result = searchApi.search(new SearchRequest()                .query(new RequestQuery()                        .language(RequestQuery.LanguageEnum.AFTS)                        .query(aftsQuery)));        return result.getBody().getList().getEntries();    }}

Edit this page

Suggest an edit on GitHub
By clicking "Accept Cookies", you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts.View Cookie Policy.

[8]ページ先頭

©2009-2025 Movatter.jp