Describe the issue
The 3.x → 4.0 upgrade guide frames wheels-legacy-adapter as the soft-landing path for teams that "need 4.0 in production now and cannot schedule the migration work yet." A reader could reasonably infer the adapter shims the application.wirebox rename described in item 10 of the guide.
It does not. Reading wheels-dev/wheels-legacy-adapter@v1.0.0's LegacyAdapter.cfc, the shims are:
renderPage() → renderView() (1.x/2.x era)
renderPageToString() (1.x/2.x era)
$legacySendEmail() (argument remap, 2.x era)
$legacyAppScopeGet(key) — an opt-in helper method, not a transparent shim of application.wirebox.foo access
- Migration scanner + deprecation logger
There is no shim that makes either of the following work after the upgrade:
// Both of these break in 4.0, even with the legacy adapter installed:
injector = new wirebox.system.ioc.Injector("wheels.Wirebox"); // package gone from vendor/wheels/
svc = application.wirebox.getInstance("emailService"); // application.wirebox doesn't exist
Why this matters
Real-world 3.x apps that bootstrap WireBox directly in Application.cfc (the canonical 2.x bootstrap pattern still present in many old codebases — confirmed in titan, the app I'm upgrading) cannot use the adapter as a transparent soft-landing. They must rewrite the bootstrap up front. The blog skeleton's framing "install the adapter, ship the upgrade, modernize incrementally" overstates what the adapter does for these apps.
Expected behavior
Either:
- The adapter actually shims this rename. Register
application.wirebox as an alias for application.wheelsdi at boot (and re-export the wirebox.system.ioc.Injector class path to point at wheels.Injector or a thin wrapper). Log a deprecation warning on use. This would make the adapter match what the rename docs imply.
- The docs explicitly call out the gap. Add a callout to the upgrade guide's item 10 saying the adapter does not cover this rename; apps that directly instantiate WireBox or read from
application.wirebox must update those references regardless of whether the adapter is installed.
Reproducer
Take any 3.x app with this canonical CFWheels 2.x-era bootstrap (titan has it; many older apps do):
// public/Application.cfc
function onApplicationStart() {
wirebox = new wirebox.system.ioc.Injector("wheels.Wirebox");
application.wo = wirebox.getInstance("global");
application.wirebox.getInstance(name = "wheels.events.onapplicationstart", initArguments = initArgs).$init(this);
}
Upgrade per the guide. Install wheels-legacy-adapter per the guide's recommendation. Run wheels start. Boot fails — wirebox package doesn't exist in vendor/wheels/.
Suggested fix
Adapter side is preferable — the docs make a promise the adapter doesn't keep. A LegacyAdapter.cfc that registers itself in onApplicationStart to:
- Set
application.wirebox = application.wheelsdi (alias)
- Provide a Java class loader override or component-mapping shim that resolves
wirebox.system.ioc.Injector to wheels.Injector (or a thin wrapper that delegates)
- Log a deprecation warning on first use of either
…would let many real-world 3.x apps install the adapter and boot without touching Application.cfc. That's the actual "soft landing" the guide promises.
If a code shim isn't feasible, please at least amend the upgrade guide's item 10 to be explicit that this rename requires manual remediation regardless of adapter installation.
Environment
- Wheels: 4.0.0-SNAPSHOT+1779
- wheels-legacy-adapter: 1.0.0
- Engine: Lucee 7.0.0.395, Java 21
- Source app: PAI Industries titan storefront (3.0.0+40 → 4.0 upgrade testbed)
🤖 Filed by Claude Code while assisting with a 4.0 upgrade testbed
Describe the issue
The 3.x → 4.0 upgrade guide frames
wheels-legacy-adapteras the soft-landing path for teams that "need 4.0 in production now and cannot schedule the migration work yet." A reader could reasonably infer the adapter shims theapplication.wireboxrename described in item 10 of the guide.It does not. Reading
wheels-dev/wheels-legacy-adapter@v1.0.0'sLegacyAdapter.cfc, the shims are:renderPage()→renderView()(1.x/2.x era)renderPageToString()(1.x/2.x era)$legacySendEmail()(argument remap, 2.x era)$legacyAppScopeGet(key)— an opt-in helper method, not a transparent shim ofapplication.wirebox.fooaccessThere is no shim that makes either of the following work after the upgrade:
// Both of these break in 4.0, even with the legacy adapter installed: injector = new wirebox.system.ioc.Injector("wheels.Wirebox"); // package gone from vendor/wheels/ svc = application.wirebox.getInstance("emailService"); // application.wirebox doesn't existWhy this matters
Real-world 3.x apps that bootstrap WireBox directly in
Application.cfc(the canonical 2.x bootstrap pattern still present in many old codebases — confirmed in titan, the app I'm upgrading) cannot use the adapter as a transparent soft-landing. They must rewrite the bootstrap up front. The blog skeleton's framing "install the adapter, ship the upgrade, modernize incrementally" overstates what the adapter does for these apps.Expected behavior
Either:
application.wireboxas an alias forapplication.wheelsdiat boot (and re-export thewirebox.system.ioc.Injectorclass path to point atwheels.Injectoror a thin wrapper). Log a deprecation warning on use. This would make the adapter match what the rename docs imply.application.wireboxmust update those references regardless of whether the adapter is installed.Reproducer
Take any 3.x app with this canonical CFWheels 2.x-era bootstrap (titan has it; many older apps do):
// public/Application.cfc function onApplicationStart() { wirebox = new wirebox.system.ioc.Injector("wheels.Wirebox"); application.wo = wirebox.getInstance("global"); application.wirebox.getInstance(name = "wheels.events.onapplicationstart", initArguments = initArgs).$init(this); }Upgrade per the guide. Install
wheels-legacy-adapterper the guide's recommendation. Runwheels start. Boot fails —wireboxpackage doesn't exist invendor/wheels/.Suggested fix
Adapter side is preferable — the docs make a promise the adapter doesn't keep. A
LegacyAdapter.cfcthat registers itself inonApplicationStartto:application.wirebox = application.wheelsdi(alias)wirebox.system.ioc.Injectortowheels.Injector(or a thin wrapper that delegates)…would let many real-world 3.x apps install the adapter and boot without touching
Application.cfc. That's the actual "soft landing" the guide promises.If a code shim isn't feasible, please at least amend the upgrade guide's item 10 to be explicit that this rename requires manual remediation regardless of adapter installation.
Environment
🤖 Filed by Claude Code while assisting with a 4.0 upgrade testbed