See the documentation page for up-to-date information.
This is a release candidate - There shouldn’t be breaking changes, but there has been a lot of refactoring. Exercise caution, and please report any bugs at https://github.com/tipsy/javalin/issues/1513
Improvements to request lifecyle
There exists an excellent description of some of the issues with the previous implementation, written by @dzikoysk.
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.
New functionality
- You can now call
Context#future
in any type of handler - You can now configure the default future callback via
ContextResolver#defaultFutureCallback
- The
JavalinJackson
implementation now registers aKtormModule
(if it finds it)