12-14-2019 04:37 PM
I am developing a custom AIO extension (SDK 3.0.1, Alfresco Community 5.2) that handles Node when it is being created based on Policy Component Bahaviour:
policyComponent.bindClassBehaviour(
NodeServicePolicies.OnCreateNodePolicy.QNAME,
ContentModel.TYPE_CONTENT,
new JavaBehaviour(this, "onCreateNode",
Behaviour.NotificationFrequency.TRANSACTION_COMMIT));
In onCreateMethod created file is posted to external service. Since the processing of this file in external service can take a long time I get a timeout in Share in upload file dialog.
I tried a workaround to run a method that posts new file to external service in a new thread but this clearly does not work due to transaction management and it fails with following exceptions:
"Thread-29" org.alfresco.error.AlfrescoRuntimeException: 11140019 Transaction must be active and synchronization is required: Thread[Thread-29,5,main]
"Thread-30" org.alfresco.service.cmr.repository.InvalidNodeRefException: Node does not exist: workspace://SpacesStore/f9e3d633-33ba-443b-811c-b3781d3f8f22 (status:null)
I don't want to block a User with longer timeout. Is there a way to allow a file to be uploaded and then run posting it to external service in the background/async? Does anybody have a working example or a suggestion what is the most optimal way to perform such tasks?
Thank you in advance,
D.
12-15-2019 12:45 PM
Behaviors should perform as quickly as possible to avoid blocking node creation and the response to the user.
Instead of posting the file to an external service from within the behavior, add a message to a queue, such as Apache Kafka or ActiveMQ. Then have a listener subscribe to that queue. When it sees that a document has been created, grab the document and post it to the external service.
I have an example that does this here:
https://github.com/jpotts/alfresco-kafka
And a sample listener is here:
https://github.com/jpotts/alfresco-kafka-listener-example
And here is a presentation from DevCon that covers it:
https://www.slideshare.net/jpotts/moving-from-actions-behaviors-to-microservices
12-15-2019 11:56 AM
You could try to externalize the code for sending the http request in an Alfresco action, then call actionService.executeAction, with async param to true, from inside the behaviour. Here you have the action service docs:
You can also check this action:
Where ThreadPoolExecuter is used to asynchronously execute code. I don't know which is the "best" option, but both should work.
Hope this helps
12-15-2019 12:45 PM
Behaviors should perform as quickly as possible to avoid blocking node creation and the response to the user.
Instead of posting the file to an external service from within the behavior, add a message to a queue, such as Apache Kafka or ActiveMQ. Then have a listener subscribe to that queue. When it sees that a document has been created, grab the document and post it to the external service.
I have an example that does this here:
https://github.com/jpotts/alfresco-kafka
And a sample listener is here:
https://github.com/jpotts/alfresco-kafka-listener-example
And here is a presentation from DevCon that covers it:
https://www.slideshare.net/jpotts/moving-from-actions-behaviors-to-microservices
12-15-2019 01:44 PM
I forgot to mention that external service returns its internal file id that is added to Node as property. Do you still recommend suggested approach in this case?
12-18-2019 12:26 PM
Jeff, thanks for useful information, especially a presentation from the DevCon, which led me to your other example (Alfresco NLP Enricher).
However, due to memory limitations I will probably stick with Redis instead of using Kafka for this particular use case.
Explore our Alfresco products with the links below. Use labels to filter content by product module.