See the documentation page for up-to-date information.
New functionality and fixes
- The
JavalinVue
plugin now has support for pre- and post-rendering (thanks to TareqK) - You can now call
Context#future
in any type of handler (thanks to @dzikoysk) - You can now configure the default future callback via
ContextResolver#defaultFutureCallback
- The
Context#seekableStream
method now closes theInputStream
- Fixed a bug where
Context#seekableStream
claimed to return a range larger than it returned - Added
Context#cachedSessionAttributeOrCompute
method, to compute absent session attributes - The
JavalinJackson
implementation 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.