-
Notifications
You must be signed in to change notification settings - Fork 1
Asynchronous operations in a web utility
Use case: In some environments, long running HTTP transactions (transactions that take longer than, say, about a minute) are not viable (they get killed). In order to execute a long-running server-side task, a web application must run the task asynchronously: It must perform one quick transaction to initiate the task, then subsequent periodic quick transactions to check on progress (percent complete) and (eventually) get the result. The common framework contains two packages that help web application developers to implement asynchronous tasks:
*.core.gwt.async: Provides a utility class helpful in developing the client-side of asynchronous tasks for GWT clients. *.standard.trackable: Provides a set of classes helpful in developing the server-side of asynchronous tasks.
Package: *.standard.trackable
A task that will be run asynchronously must be trackable (must provide the ability for clients to check on their status, and get their result when done). How to make a task trackable (server-side):
- The long-running task should be extracted to a class, called the worker class. See the HealthyWorkerMock class (under src/test) for an example of a worker class. The worker class must implement the trackable interface. It can have any number of constructors and methods required to create and initialize it, and then one method (runAndTrack()) to run the task. It also needs a setProgressRecorder() method (more on this later).
- The class that will execute (start and monitor) the task (say, a server side class in the web app) must create and initialize the worker object, and then pass it to an instance of TrackableRunner (via the TrackableRunner constructor). To run the task it calls the startTrackable() method on its instance of TrackableRunner. To (periodically) check on the progress of the task, call the getProgress() method on the TrackableRunner instance.
- By the time it is started by the TrackableRunner, the worker object will have a ProgressRecorder (passed into it via the setProgressRecorder method). Each task is assumed to consist of a known number of subtasks. When all subtasks are completed, the task is done. As it makes progress on the task, the worker object should call that ProgressRecorder to provide periodic updates on progress, by telling it how many subtasks have been completed, or incrementing the number completed.
- The web application client will call the server to initiate the task, and start a timer to remind it to check on progress in a little while. When the timer expires, call the server to check progress. If progress has reached 100%, get the results and provide them to the user. If not, optionally provide the user with an update on progress (using the percent complete value returned by the check progress operation).
How the Trackable mechanism works: TrackableRunner provides to the worker class a ProgressRecorder that knows how to pass progress updates back to it, and then runs the worker task's startAndTrack method in a separate thread (receiving progress updates via the ProgressRecorder).
Package: *.core.gwt.async
How to make a task trackable (GWT client-side):
- In the RPC classes (*Service and *ServiceAsyc classes), replace the single long-running method (say, generateReport()) with two:
- One to initiate the long-running task (initiateReportGeneration())
- One to check on progress (checkProgress())