JMAP Result reference

Benoit Tellier
Linagora Engineering
3 min readJul 9, 2019

OpenPaaS does rely on the JMAP protocol, an IETF draft for doing email over HTTP efficiently, to communicate with the Apache James mail server.

However, the JMAP specification draft had significantly been changing over the last few years. Hopefully a barcamp was held in Hanoi to bridge the gap.

At the heart of JMAP specification lies efficiency. An easy way to achieve this is to reduce the number of requests being exchanged. Think: phone battery lifetime and crappy networks might get involved. We need a mechanism to make loading email account within a single request possible. And that mechanism is… Result Reference!

JMAP allows to do several applicative requests within a single HTTP request. Result reference is a mechanism to, within a single HTTP request, allow an applicative request to reuse the results of previously executed applicative request as if it was the input specified by the user.

Here is a short example:

Email/get reuses the results of Email/query

Instead of specifying the list of email ids to be fetching we will just ask the JMAP server to be reusing the results of the previous request! easy!

Now, with my server developer hat on, I can not but refrain an expression of horror when faced with such a level of generality… I start feeling worry about types (can I pass a list of email IDs when asking a list of mailboxes), about JSON parsing, and so on.

So, James needs to be able to support Result References. Hopefully, the number of endpoints were a Result References makes sens is fairly limited: ids when getting things, destroy methods, etc…

The first thing: within a single protocol, we need to track the execution context so that an applicative request aka method can find the execution result of previous methods. So we need to create an ExecutionContext upon request reception, and pass it along so that all method can add its result and retrieve results of other methods:

We can then simply add the properties where it make sens in the builder JSON helpers:

Then we need a generic resolution mechanism: given a Result Reference Path, the method response needs to give the corresponding data. There is a bit of type dark magic going on here:
— The response can resolve several different types: be it mailboxId or emailId. We then need Java Generics to represent these different possible choices…
— We need to check types to ensure we do return the correct type to the caller
Here is what we came up with:

Then here is what you need to do in a given method for request properties accepting Result References as an input:

Tricks done…

And… In the client?

A first challenge was modifying the JMAP client to be passing several method call within a single protocol request:

Then we introduced nice builders for creating and chaining the methods:

We then added some convenience methods like “search-then-get”:

And finally executed that against a James server.

Works like a charm…

The output of this Proof Of Concept made us more confident about this specific part of the new JMAP specification. It was a great opportunity to exchange on server side requirements, and discover frontend JS libraries. Though the overall work is far from contributed, this should seriously ease future adoption of the new JMAP specification.

The authors hard working on an integration test for that feature…

--

--