How to wait until dam update asset workflow is completed instead of thread dot sleep - workflow

In AEM CQ , I am using asset manager api to write content(images uploaded from) in dam. This triggers out of the box Dam Update Asset workflow. I require to read renditions and asset properties that would be written available once the workflow is completed.
My question is how to wait until the workflow is completed for reading the asset properties instead of thread.sleep.
I tried with a recursive function call to iterate while the asset property is present. This gave null pointer exception. But when I put a thread.sleep of 50 ms inside the iteration it works for me.
Another approach I tried to get the workflow object inside the service to read workflow status but found that it takes few milliseconds for the ootb workflow to start after the content is written. Here also had to give thread.sleep.
One more attempt to use a event handler to listen workflow events. We are able to enter the event type as workflow completed. How to notify the service or jsp that the workflow is completed and we can read the asset properties and renditions?
It would be great if someone can share their suggestions feedback on the approach. Thank you.

You have the wrong approach to solve this problem. In my eyes you have exactly 2 reasonable solutions on this.
Create workflow process/step and extend the Dam Update Asset Workflow with your custom step.
OR
Create JCR observation listener and listen for Event.PROPERTY_ADDED for example or use the higher sling APIs and create event handler with the appropriate topic and than execute your business logic as soon the property you look for is added or changed.
Why not to use Thread.sleep() or other similar solution:
you don't know when the workflow is executed exactly. it may be
delayed if many asssets are uploaded or just get stuck
you cannot assure that your thread will be able to execute it's
logic. the instance may be stopped for example
creating a new tread for every resource uploaded may be expensive task. you also waste resources when you create an infinite loop and put those threads to sleep, than wake them and check again and again ... and so on until eventually the thread is able to do it's job

Related

Alfresco, recognize when a workflow is started

I use Alfresco Community 5.2 and my need is to perform some work when one of the default Alfresco's workflow is started.
I could override all the workflows definitions, but I wonder if there is a better and quicker way to do that. The perfect would be a behavior which triggers when a workflow is started.
Is there something like that ?
Any other approach is accepted. Thanks.
There isn't anything similar to a behavior for workflows that I know of, although if your workflows will always have documents attached you could consider binding a behavior to the workflow package type (I don't recall off-hand what that type is--it might just be cm:folder which wouldn't be that useful).
This is kind of a hack suggestion, but you could implement a quartz job that would run every 30 seconds or every minute or so that would use the workflow service to check to see if any new workflows have started since the last check. If so, your code could be notified and passed the workflow ID, process ID, etc.
The straightforward solution is as you suggested in your original post--just modify the out-of-the-box processes with a task listener that fires when the workflow starts.
Following Jeff suggestion, and this tutorial, I managed to implement a task creation/completion listener and do my logic inside those blocks, resolving the problem.

Why are CQ/AEM workflow being synchronous

I created a workflow where I need each process step to be asynchronous.
For example, 1st step is create thumbnails in different size that I need. After creating those thumbnails, then I would use those thumbnail to create a folio and package the contents and publish it. This is the reason the thumbnail must be created first.
Another thing I need to do is starting another workflow and I need to wait for that workflow to finish before it goes to another step. How can this be done?
It seems all steps are starting together at the same time and not being executed after one another.

How should I stop a long-running WF4 workflow?

I'm developing some Workflow 4 activities that will continuously loop and do some work. For example, one may watch an RSS feed and execute some steps as new items are added. I would like to be able to stop and restart this process cleanly (ie, in a windows service or Azure Worker Role). Currently, I have a While loop with an expression that always resolves to true, and just let the instance die when the app closes. But it seems like this is not a very clean way to stop the workflow.
How should I stop and restart the workflow?
The exact system depends a bit in the way you host your workflow but I am assuming you are using the WorkflowApplication. In that case simple option is to use the WorkflowApplication which has a Cancel method you can use to cancel execution of the workflow. You can also create a bookmarked activity and resume a stop bookmark or something similar but that might be overkill.

How to use a WF DelayActivity in an ASP.Net web based workflow

I have a web application that I am adding workflow functionality to using Windows Workflow Foundation. I have based my solution around K. Scott Allen's Orders Workflow example on OdeToCode. At the start I didn't realise the significance of the caveat "if you use Delay activities with and configure active timers for the manual scheduling service, these events will happen on a background thread that is not associated with an HTTP request". I now need to use Delay activities and it doesn't work as is with his solution architecture. Has anyone come across this and found a good solution to this? The example is linked to from a lot of places but I haven't seen anyone else come across this issue and it seems like a bit of a show stopper to me.
Edit: The problem is that the results from the workflow are returned to the the web application via HttpContext. I am using the ManualWorkflowSchedulerService with the useActiveTimers and this works fine for most situations because workflow events are fired from the web app and HttpContext still exists when the workflow results are returned and the web app can continue processing. When a delay activity is used processing happens on a background thread and when it tries to return results to the web app, there is no valid HttpContext (because there has been no Http Request), so further processing fails. That is, the webapp is trying to process the workflow results but there has been no http request.
I think I need to do all post Delay activity processing within the workflow rather than handing off to the web app.
Cheers.
You didn't describe the problem you are having. But maybe this is of some help.
You can use the ManualWorkflowSchedulerService with the useActiveTimers and the workflow will continue on another thread. Normally this is fine because your HTTP request has already finished and it doesn't really matter.
If however you need full control the workflow runtime will let you get a handle on all loaded workflows using the GetLoadedWorkflows() function. This will return acollection of WorkflowInstance objects. usign these you can can call the GetWorkflowNextTimerExpiration() to check which is expired. If one is you can manually resume it. In this case you want to use the ManualWorkflowSchedulerService with the useActiveTimers=false so you can control the last thread as well. However in most cases using useActiveTimers=true works perfectly well.

Windows Workflow: Persistence and Polling

I'm currently learning the WF framework, so bear with me; mostly I'm looking for where to start looking, not necessarily a direct answer. I just can't seem to figure out how to begin researching what I'd like in The Google.
Let's say I have a simple one-step workflow (much more complicated than that, but for simplicity's sake). This workflow needs to watch a certain record in the database to see when it changes. I don't have the capability to "push" via a trigger from the database when the row changes, so I need to poll for it every so often.
This workflow needs to be persisted to the database to be durable against restarts and whatnot as this is a long-running workflow. I'm trying to figure out the best way to get it to check every 3 minutes or so and also persist to the database. Do the persistence capabilities of the framework allow for that? It seems to be time-based. And since the workflow won't be reawakened by an external event, how does it reload from the database and check the same step it did previously again? Does it attempt the last unfulfilled activity automatically upon reloading?
Do "while" activities with a delay attached to it work at all, or can it be handled solely through the persistence services?
I'm not sure what you mean by "handled soley through persistence services"? Persistence refers only to the storing of an idle workflow.
You could have a Delay and a Code activity in a Sequence in a While loop. When in the Delay the workflow will go idle and may be persisted if necessary. However depending on how much state is needed when persisting the workflow and/or how many such workflows you would have running at any one time may mean that a leaner approach is necessary.
A leaner approach would be to externalise the DB watching and have some "DB watching" workflow service raise an event when the desired change has occured. This service would be added to Workflow runtime.
To that end you need a service contract which is defined by an Inteface with the [ExternalDataExchange] attribute. This interface in turn defines an event that the service will raise when the desired DB change is detected. It also defines a method that a Workflow can call to specify what what change this service should be looking for. The method should accept an instance GUID so that the requesting instance can be found when the DB change is detected.
In the workflow you use a CallExternalMethodActivity to call this services method. You then flow to a HandleExternalEventActivity which listen for the event. At this point the workflow will go idle and can be persisted. It will remain there until the service raises the event.