Lift Framework 3.1.0
The Lift Committers are pleased to announce the release of Lift 3.1.0 on July 2nd, 2017. This release continues our new release cadence and marks the first final release in our new cadence. This release has no code changes from the 3.1.0-RC1 release.
About Lift
The Lift Framework is a mature, advanced framework for the modern software engineer. There are Seven Things that set Lift apart from the other frameworks out there today: it's secure-by-default, developer-centric, scalable, capable of rich interactive behavior, modular, and designer-friendly. If you're new to Lift or interested in checking out what these things mean, we recommend checking out Simply Lift and The Lift Cookbook.
The Lift Mailing List is also a good resource for anyone to ask questions or just meet other Lift users. The Lift README is a good resource for figuring out how to use Lift in your project.
Changes
This release of Lift is composed of the following component releases:
Below is a list of changes since Lift 3.0 organized by the type of change and sorted by the PR number.
New Features
- (#1768) Improved handling of tuples in lift-json. Tuples can now be serialized and deserialized as heterogenous arrays in JSON instead of as objects. This feature is disabled by default to ensure we're not changing default behavior in Lift 3.1, but can be enabled by providing a
Formats
object withtuplesAsArrays
set to true. The one caveat with this functionality is that it doesn't consistently support Scala primitives, so if you're using tuples inside a larger, more complex structure you'll want to use the Java boxed types instead of Scala primitives where applicable (so,java.lang.Integer
instead ofInt
). However, if the tuple contains case classes you should be able to use primitives inside those without issue: this caveat only affects primitives directly in the tuple. The README for lift-json documents all of this, and Matt Farmer wrote a blog post demonstrating it in a more narrative style if that's more your thing. - (#1813, #1824) Session-aware Lift and Scala Futures. Especially with Lift 3's enhanced support for futures in CSS bindings and
RestHelper
, folks would find themselves firing off futures that needed to do i18n or something else that required session access, only to have that session context missing when the future actually executed. @pdyraga added a new helper,LAFutureWithSession.withCurrentSession
, aliased asS.sessionFuture
, which can be used to create anLAFuture
task that has access to the session. There is a similar helper,FutureWithSession.withCurrentSession
, that will spawn a task as a ScalaFuture
with access to the session. The resulting futures can be chained and combined with other futures and will preserve their session access. This includes all APIs in Scala'sFuture
in Scala 2.12, as well. - (#1845) Custom rendering of special Double values. Prior to M3, lift-json always serialized
NaN
,PositiveInfinity
, andNegativeInfinity
as their respective string values (NaN
,-Infinity
,Infinity
). This is actually not correct JSON, as these are not supported JSON numeric values. Many if not most JSON parsers will choke on this output, including browser parsers. One notable exception is if anyone iseval
ing JSON as JavaScript directly---but this is a very unsafe practice. As of M3, we default to rendering these asnull
instead, and provide a newRenderSettings
customization that allows you to switch back to the old rendering approach, or to switch to an approach that throws an exception if these special values are found (which can be paired withtryo
to produce aFailure
in these cases). - (#1857) Addition of the
BoxLogging
helpers. The newBoxLogging
helper provides functions for logging boxes and then continuing to operate on the box, allowing logging to become a fluent part of theBox
interaction. It provides methods that can allow for logging empties and failures, or just failures. It also allows logging these to different log levels, and allows for different adapters to be applied.
Improvements
- @n4to4 was kind enough to fix some broken links in our readme.
- (#1791) Event return normalization. If handlers to
liftVanilla.onEvent
returned false, we'd just return that value. Now, we now check for the existence ofevent.preventDefault
and trigger it andstopPropagation
if the handler returnedfalse
. We also return that return thatfalse
value for older browsers to work with. - (#1812, #1815, #1823) Full compatibility with Scala 2.12. Lift 3.0.1 was released with Scala 2.12 support, but there were still some pieces to put in place for proper continuous integration and release building before we could consider that complete. This is now done. Thanks to @SethTisue and @farmdawgnation for putting in some contortions to get this all in order.
- (#1817, #1822)
lift-json
has gained significant parser performance improvements, and is now competitive with the jawn parser in most of jawn's microbenchmarks, making it one of the fastest Scala JSON parsers across a variety of parsing scenarios. - (#1819) The mongo Java driver has been updated to version 3.4.0.
- (#1829) The MongoDB Record module now supports the MongoDB Async API calls. Now, there are a handful of
*Async
methods on the MongoDB record implementation that will returnFuture
s to the calling code, meaning you can now easily compose Mongo Record operations with other non-blocking code. Hat tip to @eltimn and @marekzebrowski for their work on this. - (#1837, #1854) Removed
FileInputStream
andFileOutputStream
usage. @eltimn moved much of Lift's internal usage ofFileInputStream
andFileOutputStream
to their more GC-friendlyjava.nio
equivalents. See this Cloudbees post for the GC impact of the old streams. This change should have no impact on your code. If you find yourself having to recompile your code to work with this change, please let us know on the mailing list, as this is meant to be a purely internal change. - (#1838) Removed some deprecated rendering methods in lift-json.
- (#1839) Closer to jQuery independence. Lift 3.0.0 debuted a new
liftVanilla
provider of JavaScript functionality on the client with an eye towards removing the Lift jQuery dependency; unfortunately, that provider was somewhat incomplete. Amongst other things, loading it still required having jQuery loaded, or at least defined. We've removed this dependency now, and continue to work to makeliftVanilla
a fully functional replacement for the jquery-dependent functionality needed for core Lift operations. - (#1853) Added Class caching for type hints in lift-json. This change should improve performance when the same type hint is seen multiple times by caching the
Class
instance we use for a particular type hint instead of invoking a class lookup each time. - (#1862) Improve error messages when we can't find a correct implicit conversion for CSS transforms. When things went wrong while trying to resolve implicit conversions to make a working CSS transform, the compiler error generated was pretty opaque. With this change, we've improved that error message to be more friendly to people without a ton of Lift experience.
Bug Fixes
- (#1832) Fixed snippet class cache. Resolved a bug in how we cache snippet class instances that caused a performance hit when using the same snippet multiple times.
- (#1841) Fixed event extraction for page fragments. When event extraction was introduced in Lift 3, it did not take into account the possibility that a page fragment might be processed---for example, as a response to an AJAX request. As a result, in these cases, the events were extracted… But they were not re-transmitted through a separate channel. Instead, they were lost entirely. We now fix that, and page fragments with extracted events will properly reference the detached event handler code that will set those handlers up properly on the client.
- (#1842) Disabled event extraction for
fixHtmlFunc
.JsExp
s that handle HTML go throughfixHtmlFunc
, which is charged with preprocessing any embedded JS so it can be served correctly for client interpretation. Unfortunately, the interaction between this preprocessing and event extraction led to some broken and unexpected behavior. We're reasoning through a deeper fix, but in the meantime even whenLiftRules.extractInlineJavaScript
is enabled,fixHtmlFunc
will not do event extraction. - (#1844) Properly handle missing servlet http requests in
buildDeferredFunction
. SometimesS.req
returns aReq
without a servletHTTPRequest
inside. Ergo, when code would callHttpRequest.snapshot
inReq.snapshot
, we would get aNullPointerException
. To fix this, we modifycurrentReq
in both definitions ofbuildDeferredFunction
so that they filter out null requests. Shout out to first-time contributor @arigoldx! - (#1852) Always suspend Comet Requests before resuming them. When a container supports request suspension, we were first scheduling a function to resume the request on a different thread and then suspending the request. While the function was scheduled in the future, the fact that it was scheduled before the suspend had definitively occurred meant there were thread schedulings where the resume could occur before the suspend had executed, leading to exceptions. We now suspend the request before scheduling the resume.
- (#1861) Add special handling for
UnavailableException
in boot. This code adds special handling forjavax.servlet.UnavailableException
. Previously, if this exception was thrown during boot, we'd swallow it because we swallowed all exceptions during boot. However, this exception is an idiomatic way to signal a full abort to the Java Application Server running the application. From now on, we will log and re-throw this exception if we see it. - (#1863) Resolve some issues with swallowing exceptions in lift-json. In some cases extraction in lift-json would go horribly wrong and swallow exceptions that occur during class instantiation. This was due to us failing to pass on an underlying exception when we run into these errors. That has now been fixed.
- (#1859) Fix LAFuture.collect/collectAll when sub-futures fail. Before, a single failed LAFuture rolled up in a
collect
orcollectAll
would cause the overall future to hang forever. We now properly fail the overall future if any contained future fails. - (aeeac27) Some minor liftsh changes to deal with some build problems.
Final Notes
This release represents six months of hard work on behalf of the contributors. Most of the contributions made to Lift are made on the contributor's own time without any kind of payment. If you use Lift, please take the time to thank a contributor the next time you see them. They'll appreciate knowing their work is valued.
Now, we look forward to the next part of the year, and begin building up to Releasing Lift 3.2.0 at the end of the year. Lift 3.2.0-M1 is currently scheduled to be released July 15, 2017. If you're interested in our progress, you can follow along from the Milestones page.
As always, please reach out to us with any questions or concerns on the mailing list. We hope you enjoy Lift 3.1.0!