This event is fired whenever a node, such as a folder or file, is deleted in the repository. The full name of this event is org.alfresco.event.node.Deleted.
Here is an example payload for this event type:
{ "specversion": "1.0", "type": "org.alfresco.event.node.Deleted", "id": "df329995-d744-427c-bafb-4a31ba7d50e3", "source": "/08d9b620-48de-4247-8f33-360988d3b19b", "time": "2021-01-27T10:57:02.586606Z", "dataschema": "https://api.alfresco.com/schema/event/repo/v1/nodeDeleted", "datacontenttype": "application/json", "data": { "eventGroupId": "acb8e25f-a340-48b5-8de8-249ae5bac670", "resource": { "@type": "NodeResource", "id": "d71dd823-82c7-477c-8490-04cb0e826e65", "primaryHierarchy": [ "5f355d16-f824-4173-bf4b-b1ec37ef5549", "93f7edf5-e4d8-4749-9b4c-e45097e2e19d", "c388532e-8da6-4d50-a6d2-4f3f3ac36ff7", "2fa2cde5-9d83-4460-a38c-cfe4ec9cca08" ], "name": "purchase-order-scan.pdf", "nodeType": "cm:content", "createdByUser": { "id": "admin", "displayName": "Administrator" }, "createdAt": "2021-01-21T11:14:15.695Z", "modifiedByUser": { "id": "admin", "displayName": "Administrator" }, "modifiedAt": "2021-01-26T10:29:42.529Z", "content": { "mimeType": "application/pdf", "sizeInBytes": 531152, "encoding": "UTF-8" }, "properties": { "cm:autoVersion": true, "cm:title": "Purchase Order", "cm:versionType": "MAJOR", "cm:versionLabel": "1.0", "cm:autoVersionOnUpdateProps": false, "cm:lastThumbnailModification": [ "doclib:1611227666770" ], "cm:description": "", "cm:taggable": null, "cm:initialVersion": true }, "aspectNames": [ "cm:versionable", "cm:author", "cm:thumbnailModification", "cm:titled", "rn:renditioned", "cm:auditable", "cm:taggable" ], "isFolder": false, "isFile": true }, "resourceReaderAuthorities": [], "resourceDeniedAuthorities": [] } }
Using the Node Browser (see Using the Node Browser) the following NodeRefs were resolved as follows:
"id": "d71dd823-82c7-477c-8490-04cb0e826e65", /app:company_home/cm:Testing/cm:Inbound/cm:purchase-order-scan.pdf (cm:content) "primaryHierarchy": [ "5f355d16-f824-4173-bf4b-b1ec37ef5549", /app:company_home/cm:Testing/cm:Inbound (cm:folder) "93f7edf5-e4d8-4749-9b4c-e45097e2e19d", /app:company_home/cm:Testing (cm:folder) "c388532e-8da6-4d50-a6d2-4f3f3ac36ff7", /app:company_home (cm:folder) "2fa2cde5-9d83-4460-a38c-cfe4ec9cca08" Store root (sys:store_root)
The event payload is telling us that a file called purchase-order-scan.pdf (i.e. data.resource.name) of type cm:content (i.e. data.resource.nodeType) was deleted by the user admin (i.e. data.resource.createdByUser.id) in the /Company Home/Testing/Inbound folder (i.e. data.resource.primaryHierarchy[0]). The deleted node had a Node ID d71dd823-82c7-477c-8490-04cb0e826e65 (i.e. data.resource.id). Note that the deleted node is soft deleted and is now available in the trash can.
When subscribing to the org.alfresco.event.node.Deleted event it’s possible to filter out anything that is of no interest. So for example, if you are interested in files with content type cm:content deleted in the folder called /Company Home/Testing/Inbound (e.g. Node ID 5f355d16-f824-4173-bf4b-b1ec37ef5549) it would be easy to configure this.
SDK5 - Plain Java
The following code shows how this can be done with SDK 5 and plain Java event handlers:
package org.alfresco.tutorial.events; import org.alfresco.event.sdk.handling.filter.EventFilter; import org.alfresco.event.sdk.handling.filter.IsFileFilter; import org.alfresco.event.sdk.handling.handler.OnNodeDeletedEventHandler; import org.alfresco.event.sdk.model.v1.model.DataAttributes; import org.alfresco.event.sdk.model.v1.model.NodeResource; import org.alfresco.event.sdk.model.v1.model.RepoEvent; import org.alfresco.event.sdk.model.v1.model.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; /** * Sample event handler to demonstrate reacting to a document/file being deleted. */ @Component public class ContentDeletedEventHandler implements OnNodeDeletedEventHandler { private static final Logger LOGGER = LoggerFactory.getLogger(ContentDeletedEventHandler.class); public void handleEvent(final RepoEvent<DataAttributes<Resource>> repoEvent) { NodeResource resource = (NodeResource) repoEvent.getData().getResource(); LOGGER.info("A file was deleted: {}, {}, {}", resource.getId(), resource.getNodeType(), resource.getName()); } public EventFilter getEventFilter() { return IsFileFilter.get() // Make sure it's a file .and(ParentFolderFilter.of("5f355d16-f824-4173-bf4b-b1ec37ef5549")); // Located in the /Company Home/Testing/Inbound folder } }
This code uses a custom ParentFolderFilter. For more information on a parent folder filter, see Software Development Kits (SDK).
For more information about how to extract all the properties from the message payload see the NodeResource object information available at Software Development Kits (SDK).
To create an SDK event handler project that uses Spring Integration follow the instructions on spring integration event handlers available at Software Development Kits (SDK).
SDK5 - Spring Integration
The following code shows how this can be done with SDK 5 and Spring Integration event handlers:
package org.alfresco.tutorial.events; import org.alfresco.event.sdk.handling.filter.EventTypeFilter; import org.alfresco.event.sdk.handling.filter.IsFileFilter; import org.alfresco.event.sdk.integration.EventChannels; import org.alfresco.event.sdk.integration.filter.IntegrationEventFilter; import org.alfresco.event.sdk.model.v1.model.DataAttributes; import org.alfresco.event.sdk.model.v1.model.NodeResource; import org.alfresco.event.sdk.model.v1.model.RepoEvent; import org.alfresco.event.sdk.model.v1.model.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.integration.dsl.IntegrationFlowAdapter; import org.springframework.integration.dsl.IntegrationFlowDefinition; import org.springframework.messaging.Message; import org.springframework.stereotype.Component; /** * Spring Integration based event handler that will execute code when a file is deleted */ @Component public class DeletedContentFlow extends IntegrationFlowAdapter { private static final Logger LOGGER = LoggerFactory.getLogger(DeletedContentFlow.class); // Use builder to create an integration flow based on alfresco.events.main.channel event channel @Override protected IntegrationFlowDefinition<?> buildFlow() { return from(EventChannels.MAIN) // Listen to events coming from the Alfresco events channel .filter(IntegrationEventFilter.of(EventTypeFilter.NODE_DELETED)) // Filter events and select only node deleted events .filter(IntegrationEventFilter.of(IsFileFilter.get())) // Filter node and make sure it is a file node .filter(IntegrationEventFilter.of(ParentFolderFilter.of("5f355d16-f824-4173-bf4b-b1ec37ef5549"))) // Filter node and make sure we got correct parent folder ID (/Company Home/Testing/Inbound) .handle(t -> handleEvent(t)); // Handle event with a bit of logging } private void handleEvent(Message message) { RepoEvent<DataAttributes<Resource>> repoEvent = (RepoEvent<DataAttributes<Resource>>)message.getPayload(); NodeResource resource = (NodeResource) repoEvent.getData().getResource(); LOGGER.info("File deleted: {}", resource.toString()); } }
This code uses a custom ParentFolderFilter. For more information on a parent folder filter, see Software Development Kits (SDK).
For more information about how to extract all the properties from the message payload see the NodeResource object information available at Software Development Kits (SDK).
To create an SDK event handler project that uses Spring Integration follow the instructions on spring integration event handlers available at Software Development Kits (SDK).
Apache Camel
The following code snippet shows how this could be done with an Apache Camel route configuration:
public class SimpleRoute extends RouteBuilder { @Override public void configure() { from("amqpConnection:topic:alfresco.repo.event2") .id("DeletedFileRoute") .log("${body}") // Log all incoming events on this topic, even those that we are not interested in .choice() .when() // When the following is true: // The event type is node deleted .jsonpath("$[?(@.type=='org.alfresco.event.node.Deleted' && " + // and the node that was deleted is a file "@.data.resource.nodeType=='cm:content' && " + // and the file is located in the /Company Home/Testing/Inbound folder "'5f355d16-f824-4173-bf4b-b1ec37ef5549' in @.data.resource.primaryHierarchy[:1])]") // Unpack the data into JSON format .unmarshal("publicDataFormat") // Call a Spring Bean with the event data .bean("deletedEventHandlerImpl", "onReceive(*, COPY)") .end(); } }
The jsonpath expression uses several of the event data properties to filter out exactly the events we are interested in.
In this case a Spring Bean with ID deletedEventHandlerImpl is called at the end of the route from where you could make the necessary ReST API calls.