com.ibm.datapower.wamt.clientAPI
Class ProgressContainer

java.lang.Object
  extended by com.ibm.datapower.wamt.clientAPI.ProgressContainer

public class ProgressContainer
extends java.lang.Object

A ProgressContainer is the vehicle that the manager uses to inform the caller (likely a user presentation) of the progress on a long-running method. Think of this as a rendezvous object. Methods are long-running probably because a device has to be communicated with via AMP. The caller will get notified via this object that there was an update in the progression and can read the new progress point from this object. The caller should block using waitForUpdate(), and then retrieve the new data via the gettr methods. Alternatively the caller could poll via hasUpdate, and then when it returns true call the gettr methods. Or if you do not need to be informed of interim progress, you could use the method waitForEnd(). If there is any return value from the long-running method, it will be available for retrieval from this object. Similarly, if there is any Exception from the long-running method, it will be available for retrieval from this object.

Typical usage looks like this:

 ProgressContainer progressContainer = longRunningCommandInvocation();
 // the invocation returns quickly but the long-running work is performed on another thread
 
 while (!progressContainer.isComplete && !progressContainer.hasError()) {
     System.out.println("Executing step " + progressContainer.getCurrentStep()
             + " of " + progressContainer.getTotalSteps() + ": "
             + progressContainer.getCurrentStepDescription());
     progressContainer.waitForUpdate();
 }
 if (progressContainer.hasError()) {
     System.out.println("Task did not complete because of error: "
             + progressContainer.getError().toString());
 } else {
     System.out.println("Task complete.");
     if (progressContainer.getResult() != null) {
         System.out.println("Result: "
                 + progressContainer.getResult().toString());
     }
 }
 

A convenience method, blockAndTrace(Level), is provided so that the above can be accomplished with much less effort:

 ProgressContainer progressContainer = longRunningCommandInvocation();
 progressContainer.blockAndTrace(Level.FINER);
 
You may also see:
 
ProgressContainer progressContainer = longRunningCommandInvocation(); progressContainer.waitForEnd();
Another common use case is to simply collect the ProgressContainers and periodically check them all for updates, get the updated data, and then display or act on it.

Also available is a correlator, which is a value which can be optionally set and retrieved by the caller to hold a value that may help correlate this background task to other items that the caller cares about. The queue processor does not look at this correlator, it is for use only by the caller. The default value of the correlator is null.

This class is NLS-enabled using message keys and arguments.

Internal comment: The thread that feeds updates to this object should always close this object via one of these methods: setComplete(),setComplete(Object), or setError(Exception). Otherwise there will be a circular reference between the task and the ProgressContainer that will prevent garbage collection of both this ProgressContainer and the task that it references.

Internal comment: This class also supports hiding of the final error/completion until the feeding thread wishes to call commit(). This is helpful when dealing with locks where the lock is released in a finally clause and the commit() invocation can also be placed in that finally clause after the lock release. Note that updates to the current step cannot be hidden, only the final result/error. For more information, see the javadoc for commit() (package-access method).

Internal comment: Generally only the Task classes will load ProgressContainers with completion and/or error data. So for that reason you won't see ProgressContainers being passed into lower-level methods. For example, if a lower-level method encounters an error condition, it will throw an exception all the way back up to the Task class instead of calling setError(e) itself. In places where you do see ProgressContainers being passed into lower-level methods, it is only for the lower-level method to increment the current step with information available only to the lower-level method.

See Also:
MacroProgressContainer

Field Summary
static java.lang.String COPYRIGHT_2009_2013
           
 
Method Summary
 void blockAndTrace(java.util.logging.Level level)
          A convenience method for waiting for the task to complete and printing the progress of each step.
 void follow(ProgressContainer that, boolean doMergeAtEnd)
          Have this ProgressContainer act as a facade to another ProgressContainer.
 java.lang.Object getCorrelator()
          Get the caller-defined correlator for this object.
 java.util.Date getCreationDate()
          Get the date this object was created.
 int getCurrentStep()
          Get the current step number for this task.
 java.lang.String getCurrentStepDescription()
          Get the textual description of the current step, resolving the message key with the argument value substitution.
 java.lang.Object[] getCurrentStepDescriptionArgs()
          Get the arguments for the description of the current step.
 java.lang.String getCurrentStepDescriptionKey()
          Get the key for the description of the current step.
 java.util.Date getCurrentStepTimestamp()
          Get the timestamp of the most recent update to this object.
 java.lang.Exception getError()
          Get the Exception that caused the task to end abnormally.
 java.util.Vector getEventList()
          Returns a Vector of step descriptions with the most recent at the end of the Vector.
 java.lang.Object getResult()
          If the task was supposed to return a result to the caller, use this method to fetch the result from the task.
 Task getTask()
          Get the task object (usually a BackgroundTask or Notification) that this ProgressContainer is related to.
 int getTotalSteps()
          Get the estimated total number of steps for this task.
 boolean hasError()
          Check if the task ended abnormally.
 boolean hasUpdate()
          A non-blocking method to check if the object has an update.
 boolean isComplete()
          Check if the task represented by this object completed successfully.
 void merge(ProgressContainer that)
          Merge all the results (both result and exception) of another ProgressContainer into this one.
 void mergeError(ProgressContainer that)
          Merge the error of another ProgressContainer into this one.
 void setCorrelator(java.lang.Object correlator)
          Set the caller-defined correlator for this object.
 java.lang.String toString()
          Create a human-readable String representation of this object.
 void waitForEnd()
          Block and wait for the object to reach "the end", where "the end" is defined as being complete or ending abnormally with an error.
 void waitForUpdate()
          Block and wait for this object to be updated.
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

COPYRIGHT_2009_2013

public static final java.lang.String COPYRIGHT_2009_2013
See Also:
Constant Field Values
Method Detail

waitForUpdate

public void waitForUpdate()
                   throws java.lang.InterruptedException
Block and wait for this object to be updated. The update may be an incremented step, completion, error, or a new number of total steps. Your thread will sleep until there is an update to this object. If you want to probe for an update without blocking, use hasUpdate().

If there is not an error and it is not complete, then the update is regarding a current step.

See Also:
getCurrentStep(), getCurrentStepDescription(), isComplete(), hasError(), hasUpdate()

waitForEnd

public void waitForEnd()
                throws java.lang.InterruptedException
Block and wait for the object to reach "the end", where "the end" is defined as being complete or ending abnormally with an error. This will not return when the hasUpdate flag is set, it will wait until either normal completion or an error completion.

See Also:
waitForUpdate()

hasUpdate

public boolean hasUpdate()
A non-blocking method to check if the object has an update. If you want to sleep until a update is available, see waitForUpdate(). An update could consist of an increment of the current step, or a change in the estimated total number of steps.

Note that this will return false if the object has completed either successfully or with an error. If you wish to check for those conditions, use isComplete() or hasError().

Note that waitForUpdate() will return on these two conditions plus if the object completes either successfully or with an error. So waitForUpdate() behaves a bit differently than this method.

Returns:
true if there is an update available, false otherwise
See Also:
waitForUpdate()

getTotalSteps

public int getTotalSteps()
Get the estimated total number of steps for this task. Calling this method will clear the hasUpdate flag for this object.

Returns:
the estimated total number of steps for this task. It is possible that the estimation may not be completely accurate, so a task may be complete when the current step is not equal to the total number of steps. To accurately check if this task is completed, use isComplete(). To accurately check if this task ended abnormally with an error, use hasError().
See Also:
getCurrentStep(), isComplete(), hasError()

getTask

public Task getTask()
Get the task object (usually a BackgroundTask or Notification) that this ProgressContainer is related to. Thus if you have the ProgressContainer, you can use this method to get the Task and then you can probe the Task to see what kind of task it is and get the Task metadata. (This assumes that the task provides public methods that allow it to be probed, which it should.)

Returns:
the task object that this ProgressContainer is related to.

getCurrentStep

public int getCurrentStep()
Get the current step number for this task. Calling this method will clear the hasUpdate flag for this object.

Returns:
the current step number for this task. The current step number should help you estimate how far this task is to approaching completion, and to provide feedback to the user that this task is moving forward with progress. For checking if this task is complete, see the documentation for isComplete().
See Also:
getTotalSteps(), getCurrentStepDescription(), getCurrentStepTimestamp()

getCurrentStepDescription

public java.lang.String getCurrentStepDescription()
Get the textual description of the current step, resolving the message key with the argument value substitution. Calling this method will clear the hasUpdate flag for this object.

Returns:
the textual description of the current step.
See Also:
getTotalSteps(), getCurrentStep(), getCurrentStepTimestamp(), getCurrentStepDescriptionKey(), getCurrentStepDescriptionArgs()

getCurrentStepDescriptionArgs

public java.lang.Object[] getCurrentStepDescriptionArgs()
Get the arguments for the description of the current step. Calling this method will clear the hasUpdate flag for this object. This should be used in conjunction with getCurrentStepDescriptionKey() if you want the values separately, or just call getCurrentStepDescription() which will resolve the message key and substitute the argument values.

Returns:
the arguments to be value substituted in the message indicated by the key.
See Also:
getCurrentStepDescriptionKey(), getCurrentStepDescription()

getCurrentStepDescriptionKey

public java.lang.String getCurrentStepDescriptionKey()
Get the key for the description of the current step. Calling this method will clear the hasUpdate flag for this object. This should be used in conjunction with getCurrentStepDescriptionArgs() if you want the key separately, or just call getCurrentStepDescription() which will resolve the message key and substitute the argument values.

Returns:
the message key for the current step description
See Also:
getCurrentStepDescriptionArgs(), getCurrentStepDescription()

getCurrentStepTimestamp

public java.util.Date getCurrentStepTimestamp()
Get the timestamp of the most recent update to this object. The timestamp will be updated when this object is constructed, a step is updated, this object is marked complete, or a task's exception is attached here to mark an abnormal end. Getting this timestamp does not clear the hasUpdate flag for this object.

Returns:
the timestamp of the most recent update to this object.

isComplete

public boolean isComplete()
Check if the task represented by this object completed successfully.

Returns:
true if the task represented by this object completed successfully. If the task should return a result to the caller, that object may be retreived using getResult(). It will return false if the task is still in process or if it ended abnormally with an error. To check if it ended with an error, use hasError(). Calling this method will not clear the hasUpdate flag for this object.
See Also:
hasError(), getResult()

getResult

public java.lang.Object getResult()
If the task was supposed to return a result to the caller, use this method to fetch the result from the task. This method should be called after isComplete returns true. Calling this method will clear the hasUpdate flag for this object.

Returns:
the result from the background task. Not all tasks return objects, it depends on the task. The returned object will be populated by the task.
See Also:
isComplete()

hasError

public boolean hasError()
Check if the task ended abnormally.

Returns:
true if the task ended abnormally. In this case, you may retrieve the Exception that cause the task to terminate by using getError(). The isComplete flag will be set to false. This will return false if the task is still executing or if it completed successfully. Calling this method will not clear the hasUpdate flag for this object.
See Also:
getError(), isComplete()

getError

public java.lang.Exception getError()
Get the Exception that caused the task to end abnormally. This method should not be called until the hasError flag is true. Calling this method will clear the hasUpdate flag for this object.

Returns:
the Exception that caused this task to end abnormally.
See Also:
hasError()

setCorrelator

public void setCorrelator(java.lang.Object correlator)
Set the caller-defined correlator for this object. Calling this method will have no effect on the hasUpdate flag for this object.

Parameters:
correlator - a caller-defined correlation value for this object. This is a value which can be optionally set and retrieved by the caller to store a value that may help correlate this background task to other items that the caller cares about. The queue processor does not look at this correlator, it is for use only by the caller. The default value of the correlator is null.
See Also:
getCorrelator()

getCorrelator

public java.lang.Object getCorrelator()
Get the caller-defined correlator for this object. Calling this method will have no effect on the hasUpdate flag for this object.

Returns:
the caller-defined correlator for this object. See setCorrelator(Object).
See Also:
setCorrelator(Object)

getCreationDate

public java.util.Date getCreationDate()
Get the date this object was created. Calling this method will not clear the hasUpdate flag for this object.

Returns:
the date this object was created.

blockAndTrace

public void blockAndTrace(java.util.logging.Level level)
                   throws java.lang.InterruptedException,
                          java.lang.Exception
A convenience method for waiting for the task to complete and printing the progress of each step. It will wait for an update, and for each step print the step number and description. When the task completes successfully it will print that and check if the task returned an object. If the task ends abnormally it will print the Exception that caused the problem.

Parameters:
level - the log level at which to generate the text messages

follow

public void follow(ProgressContainer that,
                   boolean doMergeAtEnd)
Have this ProgressContainer act as a facade to another ProgressContainer. Or in other words, have this one "follow" that one. This would be used if one long-running method is a composite or or derivation of other long-running methods. For the purpose of this explanation, I will call this the 2nd ProgressContainer and that the 1st ProgressContainer. Even though the 1st one may be partially complete, the 2nd one will look at how many more steps the 1st one has and will follow it along until the 1st one completes. Whatever result or exception that the 1st one finished with, that data will be copied into the 2nd one - this is what I call a "merge". This method will block until the 1st one finishes.

Parameters:
that - the first ProgressContainer to follow.
doMergeAtEnd - if true, will copy the result/exception data from the first one into the second one (this one). You would want to do this if the second one isn't going to follow any more ProgressContainers.
See Also:
merge(ProgressContainer)

merge

public void merge(ProgressContainer that)
Merge all the results (both result and exception) of another ProgressContainer into this one. If the other ProgressContainer that has an error or a result, then copy it into this one.

Parameters:
that - the ProgressContainer from which to copy the exception or result object from
See Also:
mergeError(ProgressContainer)

mergeError

public void mergeError(ProgressContainer that)
Merge the error of another ProgressContainer into this one. If the other ProgressContainer that has an error, then copy it into this one.

Parameters:
that - the ProgressContainer from which to copy the exception from

toString

public java.lang.String toString()
Create a human-readable String representation of this object.

Overrides:
toString in class java.lang.Object
Returns:
a human-readable String representation of this object

getEventList

public java.util.Vector getEventList()
Returns a Vector of step descriptions with the most recent at the end of the Vector.

Returns:
the Vector, each element describes a completed step
See Also:
hasError()


© Copyright IBM Corp. 2006, 2010 All Rights Reserved.