Skip to content

@Shadowfiend Shadowfiend released this Nov 15, 2016 · 599 commits to master since this release

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 to true to extract any onclick, onmouseover, and generally on* events, as well as javascript:-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, any Map can be used to find properties by passing it to Props.appendProvider.

  • Props also allows interpolation in property values, which values can be added as a Map using Props.appendInterpolationValues.

  • Improved future and async support throughout, including:

    • Wrapping any right-hand value for a CSS selector transform in a Future or LAFuture (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's lazy snippet.
    • Wrapping any RestHelper response in a Future or LAFuture 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).
  • 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 to NodeSeq in Scala. See the Scaladocs for ContentParser 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.
  • In #1584, lift-json's JField stopped being a JValue; it is now instead a type alias for (String, JValue). This is a cleaner representation, but it means that map, transform, find, and filter only operate on proper JValues, and using these on fields requires using mapField, transformField, findField, and filterField.
  • 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:
  • (#1585) CometActor behavior—comets with no type specified are no longer supported
  • (#1714) LocRewrite is now expected to return a (RewriteResponse, Box[T]) where T is the type of the menu item's param. Before it was a T rather than a Box[T].
  • (#1710) lift-json no longer uses scala.text.Document as an intermediary when rendering to a string.


  • (#1585) Sending new comets to the client in AJAX callbacks
  • (#1619) MessageCometActor/CometActor distinction allows partialUpdates with fewer bugs.


  • (#1668) Much of TimeSpan's functionality has been deprecated. TimeSpan conflated
    several different concepts, including DateTime, Duration, and Period, 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 deprecated TimeSpan functionality for
    all uses that are not as a simple millisecond Duration. 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 and pretty (previously used in conjunction with
    render to serialize JSON to a String) are now deprecated in favor of compactRender
    and prettyRender. They will be removed in Lift 3.1.0.
  • (#1742) FocusOnLoad is now deprecated in favor of S.appendJs(Focus(...))
    and/or using the HTML5 autofocus 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 are defineDbAuth
    and useSession 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 Recaps

Assets 2