Jini Print Service Tutorial

Introduction
Lesson 1. The Very Basics
Lesson 2. Print Data Attributes
Lesson 3. Lookup
Lesson 4. Print Job Status
Lesson 5. Print Job Events
Lesson 6. File Print Jobs
Lesson 7. URL Print Jobs
Lesson 8. Service Registration

Lesson 4. Print Job Status

The Jini Print Service API lets you monitor the status of your print job after you have submitted the Print Request. There are two ways to do it, by polling the print job's attributes (covered in this Lesson) and by receiving event notifications from the print job (covered in Lesson 5).

When you submit a Print Request, the Jini Print Service instance creates a Print Job object that implements interface PrintJob. In the previous Lessons, this Print Job object was never returned to our client program and we never did anything with it. However, it is possible to have the Print Job object returned when you submit a Print Request. The Print Job object lets you, among other things, examine the job's job description attributes. Various job description attributes indicate the job's state, how many jobs are ahead of it in the print queue, how many sheets it has printed, and so on. The Jini Print Service instance updates the values of these attributes dynamically as it processes the print job. Some of these attributes are mandatory and will be reported by all Jini Print Service implementations; others are optional and may or may not be reported. See package javax.print.attribute.standard for a list of all the job description attributes.

We want our example client program to report the print job's state once a second until the job is finished. Below is the example code fragment from Lesson 3 expanded to monitor and report the print job state.

Line 35 constructs a Lease Renewal Manager (LRM) which we will need later.

To monitor the print job's status, we have to get a Print Job object back when we submit the Print Request. Lines 72-73 do an alternate print() method call that returns a PrintJobAndLease object, which is just a container for a Print Job object and its associated lease object. The print() method's argument is the requested initial duration for the Print Job's lease. Line 73 specifies Lease.ANY, meaning the Jini Print Service instance should pick the initial lease duration itself. Line 74 extracts and saves the Print Job object, an instance of interface PrintJob.

A Print Job object is a leased resource. As long as you need to use the Print Job object, you have to keep renewing its lease. If the Print Job's lease expires or is canceled, the Jini Print Service instance can perform any cleanup actions needed and discard the Print Job object. This lets the Jini Print Service instance recover from a distributed failure, such as if our client program crashes or if a network outage occurs.

To do the lease renewal, we'll use the LRM we constructed back on line 35. Line 75 tells the LRM to start renewing the Print Job's lease. The first argument is the lease to be renewed, namely the Print Job's lease extracted from the PrintJobAndLease object. The second argument is the duration for which to keep renewing the lease; Lease.ANY tells the LRM to keep on renewing the lease forever until it is explicitly canceled. The third argument, null, means we're not interested in receiving event notifications about lease renewals. The LRM then takes care of renewing the Print Job's lease for us, and we can forget about it.

Now we are ready to start monitoring the Print Job's status. Line 76 sets up a polling loop that is executed once a second. A pass through the loop begins with line 78 calling the getAttributes() method on the Print Job, which returns a PrintJobAttributeSet object containing a snapshot of the Print Job's job description attribute values at that instant. Each time through the loop, we must take a new snapshot; the returned attribute set object is not updated when the Print Job's attribute values change.

PrintJobAttributeSet specifies the interface for a restricted attribute set that can contain only job description attributes. A job description attribute class implements the tagging interface PrintJobAttribute. Some printing attributes are both job level attributes that can appear in a Print Request's attribute set and job description attributes that can appear in a Print Job's attribute set; such attribute classes implement both tagging interfaces PrintRequestAttribute and PrintJobAttribute. Some printing attributes are just job description attributes that can only appear in a Print Job's attribute set; such attribute classes implement just the one tagging interface PrintJobAttribute.

We are interested in the Print Job's JobState attribute. Lines 79-80 extract the job state attribute out of the attribute set by calling the attribute set's get() method. The argument is the class of the attribute we want, namely JobState.class. The get() method returns the job state attribute upcast to class Object, so we downcast it back to class JobState and save it.

Now we use the job state attribute. Line 81 prints it out. Lines 82-84 test whether the job state is one of the three possible final states denoted by the declared constants JobState.ABORTED, JobState.CANCELED, or JobState.COMPLETED. If the job state is one of these, the job is finished and we exit the polling loop. Otherwise, the job is not finished and we stay in the polling loop, delaying for one second on line 88 before doing the next iteration. The program may print something like this:

    Job state = pending
    Job state = pending
    Job state = pending
    Job state = processing
    Job state = processing
    Job state = completed
After we exit the polling loop, we no longer need to use the Print Job object. Accordingly, line 90 tells the LRM to cancel its lease.

Lines 107-116 add exception handlers for two checked exceptions thrown by the code we added. These are needed for the code to compile.


DRAFT STANDARD VERSION 1.0 (23-MAY-2000)