D. How to customize a UWS ?
7. Serializations
As said previously all UWS resources are formatted by default in XML according to the IVOA Recommendation. With this library it is possible to manage more formats. Besides the format to use is choosen in function of the HTTP header Accept, and so, of the specified MIME types.
The classes UWSSerializer and SerializableUWSObject
The class UWSSerializer is the abstract class used to define the serialization of any UWS resource in a given format. XMLSerializer and JSONSerializer correspond respectively to the XML and the JSON formats.
Notes:
- The XML format is defined by the IVOA Recommendation thanks to this XML schema.
- The JSON format is already managed in this library. It respects the following format: JSON Model
-
The most common MIME types are already stored as constant class attributes in
UWSSerializer:
- MIME_TYPE_XML: "application/xml"
- MIME_TYPE_JSON: "application/json"
- MIME_TYPE_TEXT: "text/plain"
- MIME_TYPE_HTML: "text/html"
All UWS objects extend the abstract class SerializableUWSObject. Only one function is abstract: serialize(UWSSerializer, String ownerId). It lets calling the good method of the given UWSSerializer (ex: in JobList the function UWSSerializer.getJobList(...) is called) and may consider the given owner ID to adapt the returned content to the current user (ex: in JobList a user can not get the job of another user, he gets only its own jobs). Thus you just have to call any method of SerializableUWSObject on the UWS objects to "serialize" them.
How does it work ?
Any HTTP request sent to a UWS ends with the serialization of a UWS resource. So the corresponding UWS action has to make a serialization of the asked objects in the specified format. As said previously this format is given by the HTTP header Accept. It gives a list of allowed formats which is actually an ordered list of MIME types. The choice of the format to apply is done by the method AbstractUWS.getSerializer(String) which takes the full MIME types list.
Below is the way that the action ListJobs returns the serialization of the specified job list:
public class ListJobs<JL extends JobList<J>, J extends AbstractJob> extends UWSAction<JL, J> { ... @Override public boolean apply(UWSUrl urlInterpreter, String userId, HttpServletRequest request, HttpServletResponse response) throws UWSException, IOException { // Get the jobs list: JL jobsList = getJobsList(urlInterpreter); // Write the jobs list: UWSSerializer serializer = uws.getSerializer(request.getHeader("Accept")); response.setContentType(serializer.getMimeType()); jobsList.serialize(response.getOutputStream(), serializer, userId); return true; } ... }
AbstractUWS has a list of UWSSerializer instances: the attribute serializers. AbstractUWS.getSerializer(String) chooses the serializer corresponding to the prefered MIME types among the given list. If there is no match the default serializer (specified by the attribute defaultSerializer) is returned.
How to customize ?
You can add or remove easily some serializers to you UWS thanks to the functions: addSerializer(UWSSerializer) and removeSerializer(String mimeType).
It is also possible to iterate on all existing serializers thanks to getSerializers().
Besides you can change the default serializer with setDefaultSerializer(String).
As in the version 2 of this library, it is also possible to associate a XML document to a XSLT style-sheet. It must be done in the instance of XMLSerializer used by your UWS, with the function XMLSerializer.setXSLTPath(String). As in the previous version, the function AbstractUWS.setXsltURL(String) still works. But now it calls the function XMLSerializer.setXSLTPath(String) on the used instance of XMLSerializer.
Here is how this function could be used to set the XSLT style sheet to any XML output:
public class UWSAlgorithms extends HttpServlet { ... @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ... // Sets the XSLT URL: uws.setXsltURL(req.getContextPath()+"/styles/uws.xsl"); ... } ... }
Warnings:
- All serializers of a UWS must have a different MIME type. Otherwise addSerializer will not add the given serializer.
- The value of the attribute defaultSerializer is a MIME type and it MUST correspond to an existing serializer.
- Take care that there is always one serializer (the default one, of course) !
Trick !
Some formats are often associated with several MIME types, like XML (application/xml and text/xml). If you want to associate several MIME types to one serializer, you can add manually some entries in the map attribute serializers. For instance:
public class MyExtendedUWS extends ExtendedUWS { public MyExtendedUWS(URL baseURL) throws UWSException { super(baseURL); addUWSAction(0, new AboutAction<JobList<AbstractJob>, AbstractJob>(this)); if (hasSerializerFor(UWSSerializer.MIME_TYPE_XML)) serializers.put("text/xml", getSerializer(UWSSerializer.MIME_TYPE_XML)); } ... }(MIME_TYPE_XML="application/xml")