Lift Framework 3.0.0
The Big One
Lift 3 has been several years in the making, and includes a lot of stuff. Going
through it exhaustively would be very difficult, so some highlights will be listed
and then links will be provided to other places where a lot of the finer changes
have been announced, mentioned, and discussed.
Thanks for your patience waiting for the final release, and enjoy! More to come,
as always :)
Version Support
Currently Lift 3.0.0 is built for Scala 2.11.8. Scala 2.12.0 has a compiler bug that
prevents us from building Lift 3 for it; 2.12.1 has a fix for this bug, and we'll be
publishing a 2.12 build shortly after that is released.
Big Improvements
-
Lift-json is a bit faster to serialize thanks to elimination of the intermediate
scala.text.Document
class,
and hugely faster thanks to an optimization in the hot path of serialization by @chriswebster . -
Addition of
LiftRules.securityRules
, which allows configuring:Content-Security-Policy
support (first-class support for CSP Level 1, defaults
to allowing only same-origin resources except for images, which are allowed from
all domains, and JS, which allows unsafe eval).Strict-Transport-Security
settings (default to off).- Frame restrictions (same-origin by default)
- Whether the above restrictions should be turned off for dev run mode vs other run modes.
- Whether violations of the above restrictions should be logged in dev mode vs other run modes.
See the API documentation for
SecurityRules
for more. -
Along with
SecurityRules
and supporting progressive enhancement,LiftRules.extractInlineJavaScript
can be set totrue
to extract anyonclick
,onmouseover
, and generallyon*
events, as well asjavascript:
-style URLs, into external event handlers. These are served on a per-page JS file and allow the CSP to be set to disallow unsafe inline JS while still permitting most classic server-side JS binding done in Lift using CSS selector transforms. -
Props
allows lookup of properties in places other than Lift's .props files. In particular, anyMap
can be used to find properties by passing it toProps.appendProvider
. -
Props
also allows interpolation in property values, which values can be added as aMap
usingProps.appendInterpolationValues
. -
Improved future and async support throughout, including:
- Wrapping any right-hand value for a CSS selector transform in a
Future
orLAFuture
(this will be rendered as a spinner to the client, until the future resolves at which point the content will be sent down). This is backed by the same infrastructure used for Lift'slazy
snippet. - Wrapping any
RestHelper
response in aFuture
orLAFuture
to have it handled asynchronously using container continuations, reusing all of the extensive support that Lift's comet actors use. - Including new comets in future values for CSS selector transforms or in AJAX responses or in lazy-loaded snippets without any additional plumbing or work. This also allows including lazy-loaded snippets in AJAX responses, or lazy-loaded snippets within lazy-loaded snippets (lazyception, as it were).
- Wrapping any right-hand value for a CSS selector transform in a
-
Arbitrary parsers for Lift templates can be added using
LiftRules.contentParsers
. By default, HTML and Markdown parsers are provided, but this can be straightforwardly expanded to, for example, asciidoc, or any other template that can be parsed toNodeSeq
in Scala. See the Scaladocs forContentParser
and @joescii's blog source code for more. -
Round-trips and streaming promises for even easier async support.
-
Custom
data-
and element handling for better domain-specific templates.
In addition to these big features, following is a broader summary of changes with some duplicates.
Breaking Changes
All deprecated methods in Lift 2.6 have been removed. If you have deprecation warnings
in your 2.6 application, it will not compile for Lift 3.0.0. However, there are also other
aspects that have been changed that could not be deprecated properly in Lift 2.6.
Box.get
is no longer usable.- JavaScript handling
liftAjax
is no longer available on the client, as it has been significantly restructured.- There is now a semi-public API for Lift's few client-side functions; see lift.js. Note that this API is not yet documented and therefore not considered stable, so use it directly only with great care. That said, we also don't have any specific plans to change that API's behavior.
- Lift URIs
- Lift AJAX calls are now routed under
/lift/ajax
- Lift comet calls are now routed under
/lift/comet
- Everything under
/lift
is reserved for Lift's use. That path can be customized via
LiftRules.liftPath
. Unlike before, when you could customize AJAX and comet paths
separately, you can now only customize the top-level Lift path, and everything underneath
it is reserved for Lift's use, both present and future.
- Lift AJAX calls are now routed under
- In #1584,
lift-json
'sJField
stopped being aJValue
; it is now instead a type alias for(String, JValue)
. This is a cleaner representation, but it means thatmap
,transform
,find
, andfilter
only operate on properJValue
s, and using these on fields requires usingmapField
,transformField
,findField
, andfilterField
. - In #1568, old binding strategy based on the
bind
function is now gone. CSS selector transforms should be used instead. Several built-in snippets have been migrated away from the old bind strategy; in general, elements and attributes that were prefixed by namespaces now correspond to classes without the prefixes. If you need any help migrating, please post to the Lift mailing list. The changed snippets are:Paginator
; see thePaginator
binding migration guide for details here.ProtoUser
Crudify
LiftScreen
(now behaves likeCssBoundLiftScreen
); see theLiftScreen
binding migration guide for details here.CssBoundLiftScreen
(nowLiftScreen
)FormProcessor
(removed)TableEditor
Util
inmapper.view
- (#1585)
CometActor
behavior—comets with notype
specified are no longer supported - (#1714)
LocRewrite
is now expected to return a(RewriteResponse, Box[T])
whereT
is the type of the menu item's param. Before it was aT
rather than aBox[T]
. - (#1710)
lift-json
no longer usesscala.text.Document
as an intermediary when rendering to a string.
Improvements
- (#1585) Sending new comets to the client in AJAX callbacks
- (#1619)
MessageCometActor
/CometActor
distinction allowspartialUpdate
s with fewer bugs.
Deprecations
- (#1668) Much of
TimeSpan
's functionality has been deprecated.TimeSpan
conflated
several different concepts, includingDateTime
,Duration
, andPeriod
, which did not
have the same semantics. As a result, there were corner cases where it could behave in
very unexpected ways. In order to fix this, we've deprecatedTimeSpan
functionality for
all uses that are not as a simple millisecondDuration
. This deprecation takes effect for the
final release of Lift 3.0.0, which means the functionality in question won't be removed until Lift
3.1.0 at the earliest. Big big thanks to @arkadius for spotting this issue while trying to clean up
specs, and taking point on adding the various deprecations. - (#1710) In lift-json,
compact
andpretty
(previously used in conjunction with
render
to serialize JSON to aString
) are now deprecated in favor ofcompactRender
andprettyRender
. They will be removed in Lift 3.1.0. - (#1742)
FocusOnLoad
is now deprecated in favor ofS.appendJs(Focus(...))
and/or using the HTML5autofocus
attribute. - (#1749) Our mongo dependencies were upgraded to the latest driver that
supports some of our older customization strategies. The older customization
is now deprecated for removal in 3.1.0. In particular, these aredefineDbAuth
anduseSession
wrappers.
Prior Announcements
There have been lots of posts about the new functionality in Lift 3 over the years; following
are links to the release notes for all of the milestone and RC releases, followed by a set of
links to the Lift Weekly/Monthly Recap series that covered a lot of the early additions.
Release Notes
- Lift 3.0-M0
- Lift 3.0-M1
- Lift 3.0-M2
- Lift 3.0-M3
- Lift 3.0-M4
- Lift 3.0-M5
- Lift 3.0-M6
- Lift 3.0-M7
- Lift 3.0-M8
- Lift 3.0-RC1
- Lift 3.0-RC2
- Lift 3.0-RC3
- Lift 3.0-RC4