From 4b86c0fd68958bf5dcd26cc1d0d2e3cc1a72fe5f Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Sat, 22 Aug 2026 21:57:22 -0600 Subject: [PATCH] fix: support full null lazy dependencies --- .github/workflows/tests.yml | 5 +++ models/BaseORMService.cfc | 8 ++-- test-harness/tests/full-null/Application.cfc | 13 +++++++ test-harness/tests/full-null/FakeWireBox.cfc | 33 +++++++++++++++++ test-harness/tests/full-null/index.cfm | 37 +++++++++++++++++++ .../tests/specs/BaseORMServiceTest.cfc | 16 ++++++++ 6 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 test-harness/tests/full-null/Application.cfc create mode 100644 test-harness/tests/full-null/FakeWireBox.cfc create mode 100644 test-harness/tests/full-null/index.cfm diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4fcede1..9dd6385 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -86,6 +86,11 @@ jobs: box server start serverConfigFile="server-${{ matrix.cfengine }}.json" --noSaveSettings --debug curl http://127.0.0.1:60299 + - name: Run Adobe Full Null Regression + if: ${{ matrix.cfengine == 'adobe@2025' }} + run: | + curl --fail-with-body http://127.0.0.1:60299/tests/full-null/index.cfm + - name: Run Tests run: | mkdir -p test-harness/tests/results diff --git a/models/BaseORMService.cfc b/models/BaseORMService.cfc index ac06a45..9732d48 100644 --- a/models/BaseORMService.cfc +++ b/models/BaseORMService.cfc @@ -168,7 +168,7 @@ component accessors="true" { * @return cborm.models.util.IORMUtil */ function getOrm(){ - if ( isNull( variables.orm ) ) { + if ( !structKeyExists( variables, "orm" ) || isNull( variables.orm ) ) { variables.orm = new cborm.models.util.ORMUtilFactory().getORMUtil(); } return variables.orm; @@ -180,7 +180,7 @@ component accessors="true" { * @return cborm.models.EventHandler|cborm.models.BXEventHandler */ function getORMEventHandler(){ - if ( isNull( variables.ORMEventHandler ) ) { + if ( !structKeyExists( variables, "ORMEventHandler" ) || isNull( variables.ORMEventHandler ) ) { variables.ORMEventHandler = server.keyExists( "boxlang" ) ? new cborm.models.BXEventHandler() : new cborm.models.EventHandler() } return variables.ORMEventHandler @@ -192,7 +192,7 @@ component accessors="true" { * @return cborm.models.util.DynamicProcessor */ function getDynamicProcessor(){ - if ( isNull( variables.dynamicProcessor ) ) { + if ( !structKeyExists( variables, "dynamicProcessor" ) || isNull( variables.dynamicProcessor ) ) { variables.dynamicProcessor = variables.wirebox.getInstance( "cborm.models.util.DynamicProcessor" ) } @@ -1029,7 +1029,7 @@ component accessors="true" { * @return coldbox.system.core.dynamic.ObjectPopulator */ function getObjectPopulator(){ - if ( !isNull( variables.objectPopulator ) ) { + if ( structKeyExists( variables, "objectPopulator" ) && !isNull( variables.objectPopulator ) ) { return variables.objectPopulator } variables.objectPopulator = variables.wirebox.getObjectPopulator() diff --git a/test-harness/tests/full-null/Application.cfc b/test-harness/tests/full-null/Application.cfc new file mode 100644 index 0000000..885cd9b --- /dev/null +++ b/test-harness/tests/full-null/Application.cfc @@ -0,0 +1,13 @@ +component { + + moduleRoot = createObject( "java", "java.io.File" ) + .init( getDirectoryFromPath( getCurrentTemplatePath() ) & "../../../" ) + .getCanonicalPath(); + + this.name = "cborm-full-null-regression-#hash( moduleRoot )#"; + this.enableNullSupport = true; + this.mappings[ "/cborm" ] = moduleRoot; + this.mappings[ "/coldbox" ] = moduleRoot & "/test-harness/coldbox"; + this.mappings[ "/fullnull" ] = getDirectoryFromPath( getCurrentTemplatePath() ); + +} diff --git a/test-harness/tests/full-null/FakeWireBox.cfc b/test-harness/tests/full-null/FakeWireBox.cfc new file mode 100644 index 0000000..f415c61 --- /dev/null +++ b/test-harness/tests/full-null/FakeWireBox.cfc @@ -0,0 +1,33 @@ +component { + + variables.instanceCalls = 0; + variables.objectPopulatorCalls = 0; + variables.dynamicProcessor = { type : "dynamicProcessor" }; + variables.objectPopulator = { type : "objectPopulator" }; + + function getInstance(){ + variables.instanceCalls++; + return variables.dynamicProcessor; + } + + function getLogBox(){ + return this; + } + + function getLogger(){ + return {}; + } + + function getObjectPopulator(){ + variables.objectPopulatorCalls++; + return variables.objectPopulator; + } + + function getCallCounts(){ + return { + instance : variables.instanceCalls, + objectPopulator : variables.objectPopulatorCalls + }; + } + +} diff --git a/test-harness/tests/full-null/index.cfm b/test-harness/tests/full-null/index.cfm new file mode 100644 index 0000000..a4d5c77 --- /dev/null +++ b/test-harness/tests/full-null/index.cfm @@ -0,0 +1,37 @@ + + +wirebox = new fullnull.FakeWireBox(); +application.wirebox = wirebox; +service = new cborm.models.BaseORMService( datasource = "unused" ); + +orm = service.getOrm(); +sameOrm = service.getOrm(); +eventHandler = service.getORMEventHandler(); +sameHandler = service.getORMEventHandler(); + +dynamicProcessor = service.getDynamicProcessor(); +sameDynamicProcessor = service.getDynamicProcessor(); +objectPopulator = service.getObjectPopulator(); +sameObjectPopulator = service.getObjectPopulator(); +callCounts = wirebox.getCallCounts(); +system = createObject( "java", "java.lang.System" ); + +if ( + !isInstanceOf( orm, "cborm.models.util.support.AdobeORMUtil" ) || + !isInstanceOf( sameOrm, "cborm.models.util.support.AdobeORMUtil" ) || + system.identityHashCode( orm ) != system.identityHashCode( sameOrm ) || + !isInstanceOf( eventHandler, "cborm.models.EventHandler" ) || + !isInstanceOf( sameHandler, "cborm.models.EventHandler" ) || + system.identityHashCode( eventHandler ) != system.identityHashCode( sameHandler ) || + !isStruct( dynamicProcessor ) || + !isStruct( sameDynamicProcessor ) || + !isStruct( objectPopulator ) || + !isStruct( sameObjectPopulator ) || + callCounts.instance != 1 || + callCounts.objectPopulator != 1 +) { + throw( type = "RegressionFailure", message = "cbORM public lazy dependencies did not initialize exactly once." ); +} + +writeOutput( "PASS" ); + diff --git a/test-harness/tests/specs/BaseORMServiceTest.cfc b/test-harness/tests/specs/BaseORMServiceTest.cfc index 218778a..6b6d8c0 100755 --- a/test-harness/tests/specs/BaseORMServiceTest.cfc +++ b/test-harness/tests/specs/BaseORMServiceTest.cfc @@ -45,6 +45,22 @@ assert( 1 eq t, "CountBylastName" ); } + function testLazyDependenciesThroughPublicAPI(){ + var service = new cborm.models.BaseORMService().init(); + var system = createObject( "java", "java.lang.System" ); + + expect( system.identityHashCode( service.getOrm() ) ).toBe( system.identityHashCode( service.getOrm() ) ); + expect( system.identityHashCode( service.getORMEventHandler() ) ).toBe( + system.identityHashCode( service.getORMEventHandler() ) + ); + expect( system.identityHashCode( service.getDynamicProcessor() ) ).toBe( + system.identityHashCode( service.getDynamicProcessor() ) + ); + expect( system.identityHashCode( service.getObjectPopulator() ) ).toBe( + system.identityHashCode( service.getObjectPopulator() ) + ); + } + function testFindAllByDynamically(){ // Using Conditionals t = ormservice.findAllByLastNameLessThan( "User", "Majano" );