Lucee 8 - Smoky is loose!

The mascot for Lucee 8 is Smoky, the greatest smallest dog ever! In 1944, this 4-pound Yorkshire Terrier pulled a telegraph wire through a 70-foot pipe only 8 inches wide, saving soldiers three days of dangerous digging (Smoky on Wikipedia).

Lucee 8.0.0.304 is now available :boom:, the first stable release of Lucee 8.

Download: https://download.lucee.org/

What Lucee 8 is about

Stable, robust, fast. Lucee 8 is mostly about the engine your code runs on, not about new syntax. Lucee 7 started a lot of this work, and Lucee 8 finishes it. Most of it makes Lucee faster and lighter without any changes to your code.

  • All in on Maven. Core, extensions and Java libraries all come from Maven. You can name an extension in .CFConfig.json (or LUCEE_EXTENSIONS) by its Maven coordinate, for example {"maven": "org.lucee:mysql-jdbc-extension"}. Most bundled extensions are now lite builds that fetch their Java libraries from Maven when they install, and you can point Lucee at your own repository or mirror with maven.repository.
  • A smaller core. Markdown and SMB moved out of core into bundled extensions (LDEV-6520), so markdownToHTML() and smb:// keep working. The Janino compiler is only downloaded when it’s first needed.
  • Configuration, rewritten. Configuration loading is now declarative and lazy, and changing one setting no longer reloads the whole configuration. Everything you can set in .CFConfig.json can also be set as an environment variable or system property. A setting that comes from the environment shows as read-only in the Administrator (LDEV-6452), and ConfigSchema() gives your editor a JSON Schema for validation and autocomplete.
  • Performance. Faster UDF calls (LDEV-5933), argument and local scopes backed by arrays (LDEV-5865), pooled response buffers (LDEV-6427), concurrent application, server and session scopes that remove most lock contention under load (LDEV-6479), and faster Java object creation (LDEV-6614).
  • Virtual threads. Lucee 8 requires Java 21, so virtual threads are always available. arrayEach(), arrayMap() and friends accept parallel="none" | "thread" | "virtual" plus maxConcurrency (LDEV-6369), and <cfthread virtual="true"> runs a thread on a virtual thread.
  • Language additions. The ?? null-coalescing operator (LDEV-5343), onMissingFunction() in Application.cfc (LDEV-5094), queryColumnNames() (LDEV-5748), structIsOrdered() (LDEV-6345), and bracket notation for nested form and URL fields (LDEV-6070).
  • PDF 3.0 is bundled. <cfdocument> now renders with OpenHTMLToPDF, and <cfpdf> uses PDFBox 3.
  • On the way to Lucee 9. The perl regex engine is deprecated (LDEV-6660). It is still the default, and the new compat mode (LDEV-6432) makes switching to the Java engine easier. Try this.regex = { type: "java" }; (or "compat") on your applications.
  • The fixes from the 7.1 line are merged in, among them time zones, null handling, mail, datasource pools, sessions and the Administrator.

For the full story behind each of these, see the 8.0 release candidate announcement.

Upgrading from 7.1

  • Switch to Java 21 first. Lucee 8 requires Java 21 or newer. On Java 11 or 17 the 8.0 core will not start.
  • You don’t need to replace lucee.jar. Coming from 7.1, the existing loader can run 8.0, so you can update the core from the Administrator or by dropping the .lco file into the deploy folder.
  • If the in-place update reports an OSGi “uses constraint” error, restart the servlet engine and 8.0 will start from the downloaded core.
  • Check your .CFConfig.json. Some keys must move into their section (the debugging settings into monitoring, cacheDefault* into cache, updateProxy* into proxy). Lucee 8 ignores them at the top level without a warning. Environment variables now win over .CFConfig.json, so also check for leftover LUCEE_* variables.
  • parallel=true now uses virtual threads with no limit. If your closures use limited resources such as database connections, set parallel="thread" or maxConcurrency.

Please read the breaking changes 7.1 → 8.0 before you upgrade. It covers everything above and more.

Bundled extensions

Extension 7.1.2 8.0.0
MySQL 26.7.0 26.7.0
Microsoft SQL Server 13.2.1 13.4.0.jre11
PostgreSQL 42.7.11 42.7.11
Administrator 1.0.0.9 1.0.0.9
Documentation 1.0.0.8 1.0.0.8
S3 2.0.3.1 2.1.0.15
PDF 2.0.1.0 3.0.0.2
Image 3.1.0.11 3.1.0.11
ESAPI 3.1.0.1 3.1.0.7
Scheduler Classic 1.0.0.2 1.0.0.2
Compress 2.1.0.3 2.1.0.7
Mail 1.1.0.17 1.1.0.24
FTP 1.0.0.9 1.0.0.9
Markdown – 1.0.0.2 (new)
SMB – 1.0.0.10 (new)

All bundled extensions are final releases.

Full changelog: Changelog 8.0.0.304 — Lucee Downloads

A new home: lucee.org

Lucee 8 comes with a new website: www.lucee.org is live. Have a look around and tell us what you think.

Which version should I use?

7.1 is becoming the long-term support version, so it gets bug and security fixes only, and it’s the safe choice for production. 8.0 is where the newest features land.

Thanks

A big thank you to everyone who tested the three 8.0 release candidates. @Jim_Priest ran all his tests against 8.0, @kenricashe ran the RC in production and reported the psq config issue (LDEV-6751), and @John_Berquist found and diagnosed the name[] form field regression (LDEV-6889). That feedback is what let us release with confidence.

If you run into any problems, please report them here on the forum or in Jira (LDEV).

6 Likes

Thinking of how Docker builds work, is there a way to get all this extra downloading done once (e.g. for every loaded extension) and then preserve those results, so deployments do not need internet access and/or unexpected version updates ?

Yes. Those Maven libraries are resolved when the extension is installed, and you can do that once at image build time so the running container does not need internet access.

The official lucee/lucee images already run warmup while they are built, so the bundled extensions and their libraries are already in the image. For your own image, declare any extra extensions in .CFConfig.json (or LUCEE_EXTENSIONS) with a pinned Maven coordinate, for example {"maven": "org.lucee:s3-extension:2.1.0.15"}, and run warmup in a Dockerfile build step with LUCEE_ENABLE_WARMUP=true. Lucee then installs the extensions and stores the Maven artifacts in the image (in the mvn directory next to lucee-server). Include the version in the coordinate if you want to avoid surprise updates.

To make sure nothing is ever downloaded in the running container, set LUCEE_MAVEN_DOWNLOAD_POLICY_STARTUP=error and LUCEE_MAVEN_DOWNLOAD_POLICY_RUNTIME=error there (not in the warmup step). Lucee then blocks any Maven download and fails instead, so anything the warmup missed shows up right away. Use warn first if you want to see what would still be downloaded.

If the image build itself has no access to Maven Central, point maven.repository in .CFConfig.json (or LUCEE_MVN_REPO_RELEASES) at your own mirror. The deploy folder also works if you copy .lex files in yourself, but it was meant for hot deployment; Maven plus warmup is the better route for images.

More details are in the Downloading Lucee and Extensions for CI, Docker and Offline Installs recipe and in Warmup.

Thanks for that - tons to dig through, but the general idea is just to make sure Application.onBuild() ( IIRC Lucee already checks for that file in every Tomcat host’s web root ) createObject()'s anything with Maven javasettings yeah ?

I ended up reading Warmup :: Lucee Documentation “Pre-downloading Maven Dependencies” where it says " Since Lucee 9, warmup can do this ahead of time."

Should that be “Since Lucee 8” ?

Almost, with one correction: onBuild lives on Server.cfc (lucee-server/context/context/Server.cfc), not Application.cfc. During warmup (LUCEE_ENABLE_WARMUP=true) Lucee calls it instead of onServerStart.

In most cases you don’t need onBuild for this at all:

  • Extensions declared in .CFConfig.json (or LUCEE_EXTENSIONS) are installed during warmup, before onBuild runs.
  • Server-wide javasettings in .CFConfig.json are resolved during warmup on Lucee 8 too. Warmup loads the whole config (the same as LUCEE_CONFIG_VALIDATE=true on a normal start), so those Maven artifacts and their dependencies are downloaded into the mvn directory at build time.

The “Since Lucee 9” line in the warmup recipe is correct. It’s about a component’s own javasettings attribute: from Lucee 9, those dependencies are downloaded when the component is compiled during warmup. On Lucee 8, createObject() of such a component doesn’t download anything yet; the jars are resolved when the Java classes are first used. For those, call mavenLoad() in onBuild:

mavenLoad( [ "org.apache.poi:poi-ooxml:5.2.5" ] );

If an artifact can’t be downloaded, the exception fails the warmup, so the image build fails instead of shipping without the library.