Job Examples

    Job's require the use of the Storable object database layer.  If storable is not available, the JobManager will not function.  This is because the JobManager must store Job state, job results, and job errors in a persistent store.  Be sure to attach the JobRecord.class file to a suitable database before attempting to use the JobManager.  If you have not connected the JobRecord.class to a suitable database, you will receive an error on the INITIALIZATION channel during Apollo startup.

Creating a Job

    To create a job, you must create a class which implements the Job interface.  Your job need not extend the Thread class, all thread managment is handled by the JobManager.  The job interface is fairly simple, and facilities the communication of the running job's state and the job's return value to the rest of apollo.  The job interface can be viewed here.  The execute method of the job class is where the work is done.  While a job is running the getPercentage and the getExtendedStatus may yield information about the state of the job.  While programming a job, it is often a good idea to update these values, so the outside world can monitor the Job's progress. If you use the Status Bar Pattern, it actively monitors the Percentage and ExtendedStatus fields.  The getStatus method returns the status of the Job; there are four predefined values for this field:

0 Job Uninitialized
1 Job Running
2 Failed
3 Finished

You may also define your own status values.  In the event of a failure during the execution you may programmatically set the status value to Failed.  The JobManager will query your job using the getError() method to determine the cause of failure.  Adding the cause of failure to this reutrn value could provide invaluable data for debugging a problematic job.  If an exception is not caught by the programmers code inside the Job, the JobManager will catch the exception.  The Status of the job will be set to FAILED, and the JobManager will store the stack trace of the exception.  The stack trace aswell as the results of the getError method will be stored as the cause of failure for the Job.  Your execute() method on the Job will return a JobResult object.  In this object you set your return value, and return type code.

Examples from demo Site:
RandomNumberJob - Generates a random sequence of numbers and returns it in one of four formats

Starting a Job

    Starting a job is fairly easy.  Simply construct the Job and pass it to the startJob method on the JobManager.  Once a job is started, it is issued a JobID by the JobManager.  You should be able to read this value as soon as the Job starts running.  When a job is started a database record in the JobResult table is created. This database object will store the status, and any results or errors which the job produces.  This allows the results and errors created by a job to outlive the actual Job object.

Examples from demo Site:
LaunchJobBroker - Responsible for launching the job the user requested

Processing Job Results

    When a job is completed, getStatus() should return in the either the Failed or Finished state.  Using the JobID which was issued to your job earlier by the startJob(Job) method, you can ask the Job object using the getJob(Integer) method on the JobManager.  This will return the Job object if it is still in memory.  If the Job is no longer stored in memory, the JobRecord record will be returned instead.  The JobRecord record is the database record representing the Job.  Once you have the Job object (or the JobRecord), you can call the getJobResult() method which will return a JobResult object which holds the results of the job's execution. 

    If the Job showed it was in the failure state, you can retrieve the failure message from the JobResult with the getError() method.  It will most likely include a stack trace, which should aid in debugging.  If the job did not fail, then you should be able to retreieve it's result using the getResult() method.  Often times you will want to know what type of output is coming out of the Job.  You can retrieve the integer based field describing the result type using the getResultTypeID() method.  If you use the ResultTypeID field, it would be wise to define static final constants for the values returned using this field, there are none defined by default.  Often the ResultTypeID field is used in determining what the Mime/Type on the browser should be set to prior to transmitting the result to the remote browser.  This is done on the demo site. 

Examples from demo Site:
ResultBroker - Responsible for actually transmitting the Job Result data to the user