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.
Solved! Go to Solution.
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
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
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
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?
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.
Ask for and offer help to other Alfresco Content Services Users and members of the Alfresco team.
Related links:
By using this site, you are agreeing to allow us to collect and use cookies as outlined in Alfresco’s Cookie Statement and Terms of Use (and you have a legitimate interest in Alfresco and our products, authorizing us to contact you in such methods). If you are not ok with these terms, please do not use this website.