We’re in the process of registering an XML media type for the eXtensible Access Control Markup Language (XACML). Simultaneously, the XACML Technical Committee is working on a JSON format.
Both media types are useful in the context of another committee effort, the REST profile. This post explains what benefit these profiles will bring once approved, and how to support them in clients and servers.
Media Types Support Content Negotiation
With the REST profile, any application can communicate with a Policy Decision Point (PDP) in a RESTful manner. The media types make it possible to communicate with such a PDP in a manner that is most convenient for the client, using a process called content negotiation.
Content negotiation is not just a convenience feature, however. It also facilitates evolution.
A server with many clients that understand 2.0 may start also serving 3.0, for instance. The older clients stay functional using 2.0, whereas newer clients can communicate in 3.0 syntax with the same server.
This avoids having to upgrade all the clients at the same time as the server.
So how does a server that supports multiple versions and/or formats know which one to serve to a particular client? The answer is the
Accept HTTP header. For instance, a client can send
Accept: application/xacml+xml; version=2.0 to get an XACML 2.0 XML format, or
Accept: application/xacml+json; version=3.0 to get an XACML 3.0 JSON answer.
The value for the
Accept header is a list of media types that are acceptable to the client, in decreasing order of precedence. For instance, a new client could prefer 3.0, but still work with older servers that only support 2.0 by sending
Accept: application/xacml+xml; version=3.0, application/xacml+xml; version=2.0.
Supporting Multiple Versions and Formats
So there is value for both servers and clients to support multiple versions and/or formats. Now how does one go about implementing this? The short answer is: using indirection.
The longer answer is to make an abstraction for the version/format combination. We’ll dub this abstraction a representation.
For instance, an XACML request is really not much more than a collection of categorized attributes, while a response is basically a collection of results.
Instead of working with, say, the XACML 3.0 XML form of a request, the client or server code should work with the abstract representation. For each version/format combination, you then add a parser and a builder.
The parser reads the concrete syntax and creates the abstract representation from it. Conversely, the builder takes the abstract representation and converts it to the desired concrete syntax.
In many cases, you can re-use parts of the parsers and builders between representations. For instance, all the XML formats of XACML have in common that they require XML parsing/serialization.
In a design like this, no code ever needs to be modified when a new version of the specification or a new serialization format comes out. All you have to do is add a parser and a builder, and all the other code can stay the way it is.
The only exception is when a new version introduces new capabilities and your code wants to use those. In that case, you probably must also change the abstract representation to accommodate the new functionality.
You must be logged in to post a comment.