Let's discover what are the new features introduced by the new UWS standard version - 1.1 - and their implementation and usage with this library!
version
What version does my UWS
use?Since version 1.1 of the UWS standard, a new attribute is added to the root nodes of the XML representation of only the job list and the job.
<jobs version="1.1" ...> <jobref id="123456A" xlink:type="simple" xlink:href=".../123456A"> <phase>...</phase> </jobref> ... </jobs>
<job version="1.1" ...> <jobId>123456A<jobId> <phase>...</phase> <owner> xsi:nil="true" /> ... </job>
...also for the UWS node. This one exists only in this library and is not part of the UWS standard. It defines an XML document listing all available job lists. It is the default output of the root object of a UWS service created by this library if no home page is defined.
<uws version="1.1 ...> <description>...</description> <jobLists> <jobListRef name="..." href="..." /> ... </jobLists> </job>
A great feature introduced by UWS 1.1 is the ability to block an HTTP-GET request on /{jobs}/{job-id}. Thus in the version 1.0, a client had to poll several times per second during a more or less long time a UWS service in order to know the evolution of a given job execution. Instead, in the version 1.1, a same client has the possibility to specify that it wants a response only when either the phase of a specified job changes or a given waiting time is elapsed.
For that, nothing more than a single parameter must be provided in the
URL: WAIT
. This parameter must have a value. This value
must be an integer representing a waiting time in seconds. There are
two special values to know:
Nothing being mentionned explicitely in the UWS 1.1 standard, this library will consider any negative time the same way as for -1: unlimited waiting time.
Of course, in order to avoid useless blocking, a UWS service will
block ONLY IF the job is in an active phase.
A such phase is: PENDING
, QUEUED
or
EXECUTING
. If the job is in another phase, the "blocking
request" will return immediately.
UWS 1.1 defines an additional and optional parameter:
PHASE
. It lets specify in which phase the job must be
while performing the blocking. Thus, only one of the active
phases is allowed. If the job is not in this phase, the server
will respond immediately.
In brief, here will be the behavior of a UWS 1.1 service in function
of the given WAIT and PHASE parameters: (in the table below
NO
means that no blocking is done.)
PENDING | QUEUED | EXECUTING | COMPLETED, ABORTED, ERROR, ... | |
---|---|---|---|---|
/{jobs}/ {job-id} | NO | |||
/{jobs}/ {job-id} ?WAIT=0 | NO | |||
/{jobs}/ {job-id} ?WAIT=2 | Block 2 seconds MAX | NO | ||
/{jobs}/ {job-id} ?WAIT=2&PHASE=EXECUTING | NO | Block 2s. MAX | NO | |
/{jobs}/ {job-id} ?WAIT=-1 | UNLIMITED WAITING DURATION | NO |
In function of the server needs and limitations, the blocking strategy may not be always the same. For instance, a maximum waiting time may be set, even in case of unlimited blocking. Another example is to limit the number of blocking requests that a user can perform on a same job. Both of these strategies/policies are proposed by the UWSLibrary and corresponds to the following classes: LimitedBlockingPolicy and UserLimitedBlockingPolicy. But obviously, as in the rest of this library, customization is possible with an interface: BlockingPolicy. Thus, you can easily define your own blocking strategy.
To set the strategy you want to use with the library, you have to use the function: setWaitPolicy(BlockingPolicy). This function exists in UWSService and in UWSServlet.
// POLICY 1: Block WAIT request at most 1 minute (default) setWaitPolicy(new uws.service.wait.LimitedBlockingPolicy(60)); // POLICY 2: Block WAIT request at most 1 hour (1st parameter) // AND limit blocking requests by user and job to 3 maximum (2nd parameter) // ; when there is a new incoming request, the oldest one is stopped (3rd parameter): setWaitPolicy(new uws.service.wait.UserLimitedBlockingPolicy(360, 3, true));
In Java, it is not possible to detect when the client stops waiting an answer, though it is notified at a TCP level. For that reason, it is really interesting to limit the blocking duration per job but also per user. Indeed, it is very often that a user sends a request from a browser tab, and stops it few seconds after when he realizes the response is slower than expected, or just because he does not want to wait any more. In such case, a Java servlet does not get the abortion notification and keeps blocking. That's why choosing a specific blocking policy can be very appreciated by your server, particularly if your UWS service is popular.
The default policy set by the UWSLibrary is a LimitedBlockingPolicy with 1 minute as maximum waiting time.
When several occurrences of the parameter
WAIT
are provided, only the one with the
smallest positive value is kept.
If more than one PHASE
parameter value is
found, only the last legal occurrence is taken into account.
No. The character case is not important for the parameter names as well as for their values.
UWS 1.1 defines the three following HTTP-GET parameters to get the jobs list in order to filter the output:
Parameter | What does it do? | Examples |
---|---|---|
PHASE |
Only the job which are in the specified execution phase must
be returned. If this parameter is repeated, the returned
jobs must be in one of the specified phases. Allowed values: any legal execution phase. |
|
AFTER |
This filter selects only jobs created
(strictly) after the given date. Allowed values: ISO-8601 dates. |
|
LAST |
This filter is kind of special. It actually sorts the jobs
by descending creation time (i.e. from the most recently
created job to the oldest one) and returns
only the N most recently created jobs. Allowed values: a positive value. |
|
Since UWS 1.1, the destruction of a job is not any more the only
solution to save disk memory. When archiving a job (i.e. changing the
execution phase into ARCHIVED
), all its results are
definitely deleted. However, all its metadata are still there. So it
is still possible to know how an archived job has been initialized and
executed (how long?, did it succeed?, ...).
Indeed, in order to keep a backward compatibility with UWS 1.0, archived jobs must never be listed when requesting /{jobs}.
...a PHASE
filter is provided with the value
ARCHIVED
. This is actually the only way to get a list
of all archived jobs.
Since the UWS 1.1 document does not define a standard way to put a job
into the ARCHIVED
phase, the UWSLibrary has established
3 policies linked to the destruction of a job. All of them are
identified with the Enum class JobDestructionPolicy:
ALWAYS_DELETE
: jobs will never be archived. This is the
default UWS 1.0 behavior, and still the default value.
ARCHIVE_ON_DATE
: when the destruction time of a job is
reached, instead of being definitely destroyed, the job is archived.
A user deletion request will still destroy the archived job.
ALWAYS_ARCHIVE
: if the job is not already archived,
reaching the destruction time or receiving a deletion request from
the user will archive the job.
This policy can be easily changed for a specified job list using the function JobList.setDestructionPolicy(JobDestructionPolicy).
ALWAYS_DELETE
policy since it is the only one
possible in UWS 1.0.
ACTION=DELETE
on the job.
ALWAYS_ARCHIVE
??ALWAYS_ARCHIVE
, the first attempt
of destruction of a non-archived job will indeed archive it. So a
second destruction request is needed to definitely get rid of it.
In UWS 1.0 a result node in the XML representation did not give any information on the type and the size of the result. This is now something made possible in UWS 1.1 with the two following optional attributes:
mime-type
: MIME type of the result.size
: size (in bytes) of the whole result file.The library does not set automatically neither the size nor the MIME type of the result. You have to do it by yourself when implementing a JobThread. If the result is a file, the size can easily be got thanks to the function UWSFileManager.getResultSize(Result, UWSJob).
If you interested in testing a UWS 1.1 compatible service, you can download the WAR example for UWS 1.1. It is already ready for deployment ; nothing to configure. When deployed, you can access it through the URL: http://localhost:8080/uws1.1/uws. A very minimalist form will let you create a job. Jobs of this example accept only one parameter named "time" which corresponds to the execution duration in seconds you want ; it will be just a thread sleeping every second until reaching the specified time.
Everything, including the job work and parameters, can be configured in
the only Java class available in this WAR archive:
WEB-INF/classes/TestServlet.java
. It can be easily compiled
using the ANT script located directly into WEB-INF
under
the name build.xml
:
.../uws1.1/WEB-INF$ ant
Some instructions are written as comments in the Java class so that helping you to locate interesting parts of the code, though it is not at all long and complicated.
Enjoy!
And if you encounter any bug or difficulty, or if a UWS 1.1 is missing
or baldy implemented, do not hesitate to
send be an email.