ContentHandlerServer provides methods
to get new Invocation requests, to finish the processing
of requests and to get the access control information.
This server interface extends {@link ContentHandler}
to make available the registration information for types,
suffixes, actions, ID, etc.
Instances are thread safe.
Responding to an Invocation
Content handler applications process requests using
either blocking calls to {@link #getRequest getRequest} or can be
notified of
new requests with the {@link #setListener setListener} method.
A content handler receives an Invocation by calling
{@link #getRequest getRequest}.
The content handler should use the
{@link Invocation#getAction Invocation.getAction}
method to determine the requested action and act on the content
appropriately.
The content handler will typically call the
{@link Invocation#open Invocation.open} method to read the content.
The open method returns a Connection from the Generic
Connection framework that provides access to the content.
When the content handler is finished processing the Invocation,
it must call the
{@link #finish finish} method to report the status.
If a response was required the status and parameters are returned
to the invoking application.
Required Response to the Invoking Application
The invoking application decides whether it needs a response and
sets the request state before calling
{@link Registry#invoke Registry.invoke}.
When an Invocation is completed either by using the
{@link #finish finish}
method or when the AMS is handling an error condition,
the {@link Invocation#getResponseRequired Invocation.getResponseRequired}
method is checked.
If it is true , then the values from the Invocation are
queued to the invoking application with the status set
by the ContentHandler or AMS.
When a response is queued, it will be dispatched to the invoking
application.
If a response is not required, it is not delivered to the invoking
application and the invoking application is not started.
Chaining Content Handlers
Content handlers link Invocations that are part of
a user-driven task and depend on each other as part of a transaction.
Suppose an application A creates an invocation
a. When invoked, it is dispatched to content
handler B which in-turn creates an invocation b
and it is dispatched to content handler C. C displays the
content and returns a response b' to B, B in turn
completes processing and returns a response a' to A.
The implementation MUST have the capacity and mechanisms to support
the chaining of requests required for an application to invoke a
content handler, and the content handler invoking another content
handler, and for each content handler to return a response.
This chain length of two active invocations is the minimum
requirement. The implementation should not artificially
limit the number of invocations and responses that are supported
except as constrained by the resources of the device.
To maintain continuity across the applications,
chained invocations are part of the same transaction.
Invoking an Invocation places it in a transaction.
The transaction maintains the sequence of invocations
across all of the applications involved.
The transaction maintains the invocations regardless of whether
a single application can run at a time or the applications
execute in parallel in different runtime environments. The
transaction is used to record and manage the steps in processing and
dispatching to applications.
For simple non-chaining use cases that involve only two
applications with a single invocation and response,
only the methods
{@link #getRequest getRequest}, {@link #finish finish},
{@link Registry#invoke Registry.invoke}, and
{@link Registry#getResponse Registry.getResponse} are needed.
For chained use cases, the methods {@link Registry#invoke Registry.invoke}
and {@link Invocation#getPrevious Invocation.getPrevious}
are used to establish
the sequence and to retrieve the previous Invocation.
The {@link Registry#invoke Registry.invoke} method places the new
Invocation in the same transaction as a previous Invocation.
The previous Invocation will be held in the transaction until
the new Invocation is completed. When the response to the new
Invocation is returned, the previously active Invocation can be
retrieved with {@link Invocation#getPrevious Invocation.getPrevious}
so the content handler can complete its processing.
An Invocation can be delegated to another handler with the
{@link Registry#reinvoke Registry.reinvoke} method.
Responses to the reinvocation will be queued to the original invoking
application.
Handling Faults
If the content handler cannot or does not correctly handle the
Invocation, then the AMS MUST handle it correctly.
These actions prevent an incorrectly written content
handler from being unresponsive or being run repeatedly but never
processing queued invocations.
-
If an Invocation with a status of
ACTIVE is dequeued by
the content handler, but the handler does not call
{@link #finish finish}
or make a request to chain a new Invocation to the ACTIVE
invocation before the content handler exits, then the AMS MUST
complete the request with an ERROR status.
This ensures that the invoking application
will always get a response, if required, for each invocation
regardless of whether the content handler correctly handles it.
-
If the content handler is not running, or exits before processing
all queued requests or responses, then it MUST be started.
The content handler is expected to dequeue at least one
invocation that was queued before it was started.
If it does not dequeue any pending Invocations or can not be started,
then Invocations that were in the queue for the content handler
before it was started MUST be handled as follows:
- Invocation requests with a status of
ACTIVE
are completed with the ERROR status.
- Invocation responses are discarded.
- Invocations queued after the content handler was started are
retained and will require it to be restarted.
This serialization of queued requests and starting the content
handler
addresses a race condition. This condition may occur when the
content handler is active but exits before processing Invocations that
were queued after it was started or it last called
{@link #getRequest getRequest} or
{@link Registry#getResponse Registry.getResponse}.
Invocations and invocation state MUST NOT be preserved
across soft and hard restarts of the device software including
unexpected power interruptions. |