See the documentation page for up-to-date information.
New functionality and fixes
- The
JavalinVueplugin now has support for pre- and post-rendering (thanks to TareqK) - You can now call
Context#futurein any type of handler (thanks to @dzikoysk) - You can now configure the default future callback via
ContextResolver#defaultFutureCallback - The
Context#seekableStreammethod now closes theInputStream - Fixed a bug where
Context#seekableStreamclaimed to return a range larger than it returned - Added
Context#cachedSessionAttributeOrComputemethod, to compute absent session attributes - The
JavalinJacksonimplementation now registers aKtormModule(if it finds it)
Improvements to request lifecyle
There exists an excellent description of some of the issues with the previous implementation, written by @dzikoysk. Huge thanks to him for diagnosing the issue and providing a fix.
To provide a short summary,
Javalin used to store the result the user wished to return to the client either as a
CompletableFuture or an InputStream. This depended on if you called
Context#future or Context#result. Calling one of these methods would clear any
value set by the other one, and when it was time to finish the request lifecycle,
Javalin would branch into two ways of writing a response
(async or sync). This could lead to race conditions in certain cases.
The issue was solved by consolidating the two backing fields into a single CompletableFuture,
and wrapping it in an AtomicReference. This also allowed us to rework the request lifecycle
into a chain of CompletableFuture results. This makes previously impossible things possible,
such as calling Context#future in all types of handlers (before, after, exception, error).
Javalin still runs synchronously if you don’t pass it a CompletableFuture.
If you pass Javalin a String result by calling ctx.result("My String"),
Javalin will transform this into an already completed future,
and there will be no need to start an async context. There should be no changes to the
existing behavior of Javalin apps. Calling Context#result or Context#future will now
always close previous streams and cancel previous futures.
It’s also worth noting that when you pass a non-completed CompletableFuture in, for example,
a before, then the request will be lifted out of Jetty’s ThreadPool, and
the rest of handlers (http, after, exception, error) will be appended
to this CompletableFuture as a next stage. This means it will be executed in the ThreadPool
that was responsible for completion of the original non-completed CompletableFuture.
Improvements to response writing
The JavalinResponseWrapper class, which handled compression and response writing has been
completely rewritten. This should fix potential bugs with streams not being closed properly.