Before you submit a Print Request, you can register an event listener with the Print Request that will receive event notifications as the Jini Print Service processes the resulting Print Job. You can register to receive three kinds of events:
We want our example client program to report the print job's state only when it changes using print job event notifications. Below is the example code fragment from Lesson 4 expanded to report print job state changes using print job events.
To process a Jini event,
we need an event listener object
which must be a remote object
implementing interface net.jini.core.event.RemoteEventListener.
Lines 39-67 declare our event listener class, PrintJobEventListener.
The key method is notify() on lines 48-66.
Whenever a print job event arrives,
the notify() method gets called,
as explained later.
On lines 108-118, we set up the print job event listener.
Lines 109-117 call the Print Request's
addEventListener() method.
This is done after we create the Print Request
but before we submit the Print Request to be printed;
adding the event listener at this point
ensures that we will receive all event notifications
from the point of submission onwards.
The first five arguments specify
which print job events we want to receive.
All these arguments except the third
are false or null
indicating we don't want to receive
the corresponding events.
The third argument is an array of Class objects
specifying the printing attribute category or categories
about which we want to receive event notifications.
Here we specify just the one attribute category we're interested in,
JobState.class.
We will therefore receive an event notification
whenever the Print Job's job state changes,
but not when any other Print Job attributes change.
The sixth argument is the event listener object
that will receive the event notification,
a new instance of class PrintJobEventListener.
The seventh argument is a handback object
which we won't use here, so it is set to null.
The eighth and final argument
is the requested initial duration
for the event registration's lease;
Lease.ANY means the Jini Print Service instance
should pick the initial lease duration itself.
The Print Request's addEventListener() method
returns an EventRegistration object.
From that we extract the event registration's lease
and pass it to the LRM,
telling the LRM to keep renewing it forever
until explicitly canceled.
Lines 119-122 submit the Print Request and get back a Print Job as before. We keep the polling loop to detect when the Print Job finishes, but we will poll less frequently, once every 10 seconds instead of once every second. Also, we will not print the job state in the polling loop; instead, our event listener will print the job state.
As the Jini Print Service instance
processes the Print Job,
it sends a PrintJobEvent
to our event listener
whenever the Print Job's job state changes.
When the event arrives,
the event listener's notify() method on line 48 is called,
with the event passed in as the argument.
Line 53 downcasts the event object
from the superclass net.jini.core.event.RemoteEvent
back to the actual class
PrintJobEvent.
Line 55 calls the print job event's getAttributes() method,
which returns a
PrintJobAttributeSet
containing just the attribute or attributes that changed
from among the monitored attribute categories
we specified when we registered the event listener.
This method can throw a ClassNotFoundException or an IOException,
handled on lines 58-65,
if there is a problem unmarshaling the attribute set object.
In our case,
we know that the only attribute that could have changed
is the job state,
so lines 54-55 extract the new value of the job state attribute
from the attribute set,
and line 56 prints it out.
The program may print something like this:
Job state = pending
Job state = processing
Job state = completed
After the Print Job finishes and we exit the polling loop,
we no longer need to use the Print Job object
and we no longer need to receive print job event notifications.
Accordingly, lines 137-138 tell the LRM
to cancel both those leases.
So which approach is better for monitoring Print Job status, polling or events? Both have their downsides. To detect state changes in a timely manner using polling, you have to poll frequently, which chews up network bandwidth continually even when the state is not changing. Events use network bandwidth only when the state changes, but on the other hand, events are not necessarily reliable; they may get lost, be delayed, or arrive out of order in a distributed system. For complete reliability, you may need a hybrid approach: rely mainly on event notifications to detect state changes, but poll the state occasionally as well in case a state change reporting event got lost. This example uses the hybrid approach -- events are used to print out the job state, but polling is used to detect when the job finishes. If we relied on an event (instead of polling) to detect when the job finishes and that event got lost, our example program would never terminate.
DRAFT STANDARD VERSION 1.0 (23-MAY-2000)