├── .gitbook └── assets │ ├── AsyncScheduler.png │ ├── Bootstrapper.jpg │ ├── BugsCostMoney.png │ ├── CacheBox.png │ ├── CacheExample_cache_snapshot.png │ ├── ColdBox Virtual App
Life-Cycle.png │ ├── ColdBoxLifecycles.jpg │ ├── ColdBoxLifecyclesProxy.jpg │ ├── ColdBoxLogo2015_300.png │ ├── ColdBoxMajorClasses.jpg │ ├── ColdBoxProxy.png │ ├── ColdBoxScheduler.png │ ├── ColdBoxSimpleMVC.png │ ├── ColdBoxTestingClasses.png │ ├── Coldbox-cfc.jpg │ ├── CommandBoxLogo.png │ ├── ControllerLayer.jpg │ ├── ControllerWithSettingStructures.jpg │ ├── DecoratorPattern.png │ ├── EventCachingFlow.jpg │ ├── EventHandlerInjection.jpg │ ├── EventHandlerModelRequested.jpg │ ├── EventHandlers.jpg │ ├── FlashRAMSequence.jpg │ ├── HandlerToTestRelationship.png │ ├── InterceptorChain.gif │ ├── LayoutViewCombinations.png │ ├── LogBox.png │ ├── MVC (1).png │ ├── MVC+.png │ ├── MVC+ORM.png │ ├── MVC+objects.png │ ├── MVC.png │ ├── ModuleConfig.jpg │ ├── Modules.png │ ├── ModulesActivation.jpg │ ├── ModulesLayoutLookupFalse.jpg │ ├── ModulesLayoutLookupTrue.jpg │ ├── ModulesLifecycle.jpg │ ├── ModulesRegistration.jpg │ ├── ModulesUnload.jpg │ ├── ModulesViewLookupFalse.jpg │ ├── ModulesViewLookupTrue.jpg │ ├── New Logging Queues.png │ ├── RequestContextDecorator.png │ ├── Screen Shot 2020-08-05 at 2.41.20 PM.png │ ├── Screen Shot 2020-12-16 at 5.58.20 PM.png │ ├── ServiceLayers.jpg │ ├── TestingClasses.png │ ├── WireBox.png │ ├── app_template.png │ ├── async-programming.png │ ├── blog-ColdBox67.png │ ├── blog-ColdBox68.png │ ├── cachedExecutor.png │ ├── cachemonitor.jpg │ ├── coldbox-7-0-0-release.png │ ├── coldbox-7-1-0-release.jpg │ ├── coldbox-7-2-0-release.jpg │ ├── coldbox-async-packages.png │ ├── coldbox-engine-support-2021.png │ ├── coldbox-engine-support.jpeg │ ├── coldbox-engine-support.png │ ├── coldbox-family.png │ ├── coldbox-logo.png │ ├── coldbox-vegas-training-october-2022.png │ ├── coldbox6.2-async-tests.png │ ├── coldboxlogo2015_300.png │ ├── commandbox-terminal.png │ ├── commandbox.png │ ├── eventdriven.jpg │ ├── eventhandler-around.jpg │ ├── eventhandler-prepost (2) (2) (2) (1) (1) (1) (1) (1) (1) (1).jpg │ ├── eventhandler-prepost (2) (2) (2) (1) (1) (1) (1) (1) (1).jpg │ ├── eventhandler-prepost (2) (2) (2) (1) (1) (1) (1) (1).jpg │ ├── eventhandler-prepost (2) (2) (2) (1) (1) (1) (1).jpg │ ├── eventhandler-prepost (2) (2) (2) (1) (1) (1).jpg │ ├── eventhandler-prepost (2) (2) (2) (1) (1).jpg │ ├── eventhandler-prepost (2) (2) (2) (1) (2).jpg │ ├── eventhandler-prepost (2) (2) (2) (1).jpg │ ├── fixedexecutor (1) (1).png │ ├── fixedexecutor (1).png │ ├── fusion-reactor-profiler.png │ ├── handlertotestrelationship.png │ ├── image (1) (1).png │ ├── image (1).png │ ├── image (2).png │ ├── image (3) (1) (1).png │ ├── image (3) (1).png │ ├── image (3).png │ ├── image (4) (1).png │ ├── image (4).png │ ├── image (5).png │ ├── image.png │ ├── logo-gradient-dark.png │ ├── luis-majano-profile-small.jpeg │ ├── luis-majano-profile.jpeg │ ├── luis-majano-small.jpeg │ ├── luismajano.jpg │ ├── modelguide_book.png │ ├── modelguide_bookservice.png │ ├── mvc-overview.png │ ├── ortus-community-square-small.png │ ├── ortussolutions_button.png │ ├── overview_testing.png │ ├── project.png │ ├── request-lifecycle (1) (1) (1).png │ ├── request-lifecycle (1) (1).png │ ├── requestcollectiondatabus (1) (1) (1).jpg │ ├── requestcollectiondatabus (1) (1).jpg │ ├── resourceful_routes.PNG │ ├── resthandler.png │ ├── route-record.png │ ├── runnables.png │ ├── scheduledExecutor.png │ ├── shalom.jpg │ ├── simplemodelclassdiagram.png │ ├── singleThreadExecutor.png │ ├── singleton-renderer.png │ ├── space-ninja200.png │ ├── spaghetti.png │ ├── tasks-with-and-without-overlaps.png │ ├── tasks-with-no-overlaps.png │ ├── template-tests-commandbox-runner.png │ ├── template-tests-runner.png │ ├── testharness.png │ ├── testing-lifecycle.png │ ├── timermonitor.png │ ├── tracer.png │ └── wirebox-transient-cache.png ├── README.md ├── SUMMARY.md ├── architecture-concepts └── how-coldbox-works.md ├── digging-deeper ├── coldbox-proxy │ ├── README.md │ ├── caveats-and-gotchas.md │ ├── getting-started.md │ ├── proxy-events.md │ ├── standard-return-types.md │ ├── the-base-proxy-object.md │ └── the-event-handlers │ │ ├── README.md │ │ ├── distinguishing-request-types.md │ │ └── renderdata.md ├── controller-decorator.md ├── flash-ram │ ├── README.md │ ├── creating-your-own-flash-scope.md │ ├── flash-storage.md │ └── using-flash-ram.md ├── html-helper.md ├── promises-async-programming │ ├── README.md │ ├── async-pipelines-and-futures.md │ ├── executors.md │ ├── parallel-computations.md │ └── scheduled-tasks.md ├── recipes │ ├── README.md │ ├── application-templates.md │ ├── building-a-simple-basic-http-authentication-interceptor.md │ ├── building-rest-apis.md │ ├── clearing-the-view-cache.md │ ├── coldbox-exception-handling.md │ └── debugging-coldbox-apps.md ├── request-context-decorator.md ├── rest-handler.md └── scheduled-tasks.md ├── for-newbies └── 60-minute-quick-start │ ├── README.md │ ├── adding-a-layout.md │ ├── adding-a-model.md │ ├── installing-coldbox.md │ ├── linking-events-together.md │ ├── my-first-coldbox-application.md │ ├── my-first-handler-and-view.md │ ├── next-steps.md │ ├── restful-data.md │ └── working-with-event-handlers.md ├── getting-started ├── configuration │ ├── README.md │ ├── bootstrapper-application.cfc.md │ ├── coldbox.cfc │ │ ├── README.md │ │ ├── configuration-directives │ │ │ ├── README.md │ │ │ ├── cachebox.md │ │ │ ├── coldbox.md │ │ │ ├── conventions.md │ │ │ ├── environments.md │ │ │ ├── flash.md │ │ │ ├── interceptors.md │ │ │ ├── interceptorsettings.md │ │ │ ├── layouts.md │ │ │ ├── layoutsettings.md │ │ │ ├── logbox.md │ │ │ ├── modules.md │ │ │ ├── modulesettings.md │ │ │ ├── settings.md │ │ │ └── wirebox.md │ │ └── system-settings-java-properties-and-environment-variables.md │ └── using-settings.md ├── conventions.md ├── getting-started-guide.md └── installation.md ├── hmvc └── modules │ ├── README.md │ ├── core-modules.md │ ├── layout-and-view-renderings │ ├── README.md │ ├── default-module-layout.md │ ├── explicit-module-renderings.md │ ├── layout-view-discovery.md │ ├── overriding-layouts.md │ └── overriding-views.md │ ├── locations.md │ ├── models.md │ ├── module-async-scheduling.md │ ├── module-bundles.md │ ├── module-cf-mappings.md │ ├── module-dependencies.md │ ├── module-event-executions.md │ ├── module-helpers.md │ ├── module-inception.md │ ├── module-layout │ ├── README.md │ └── changing-the-module-layout.md │ ├── module-service │ ├── README.md │ ├── common-methods.md │ ├── loading-a-la-carte-modules.md │ ├── loading-new-modules.md │ ├── module-activation.md │ ├── module-events.md │ ├── module-lifecycle.md │ ├── module-registration.md │ └── module-unloading.md │ ├── moduleconfig │ ├── README.md │ ├── environment-control.md │ ├── interceptor-events.md │ ├── module-settings.md │ ├── public-module-properties-directives.md │ ├── the-configure-method.md │ └── the-decorated-variables.md │ ├── parent-configuration.md │ ├── request-context-module-methods.md │ └── url-routing │ ├── README.md │ ├── default-route-execution.md │ └── module-routes-files.md ├── readme ├── about-this-book │ ├── README.md │ └── author.md ├── contributing-guide.md ├── release-history │ ├── README.md │ ├── whats-new-with-7.0.0 │ │ ├── README.md │ │ └── release-notes.md │ ├── whats-new-with-7.1.0.md │ ├── whats-new-with-7.2.0.md │ ├── whats-new-with-7.3.0.md │ └── whats-new-with-7.4.0.md ├── upgrading-to-coldbox-7.md ├── what-is-coldbox.md └── what-is-mvc.md ├── testing ├── testing-coldbox-applications │ ├── README.md │ ├── coldbox-testing-classes.md │ ├── common-methods.md │ ├── integration-testing │ │ ├── README.md │ │ ├── http-testing-methods.md │ │ ├── life-cycle-events.md │ │ ├── test-annotations.md │ │ ├── test-setup.md │ │ ├── testing-without-virtual-application.md │ │ └── the-execute-method.md │ ├── interceptor-testing.md │ ├── model-object-testing.md │ ├── test-harness.md │ └── tips-and-tricks.md └── testing-quick-start.md └── the-basics ├── event-handlers ├── README.md ├── event-caching.md ├── executing-events.md ├── executing-routes.md ├── getting-and-setting-values.md ├── how-are-events-called.md ├── http-method-security.md ├── implicit-methods.md ├── interception-methods │ ├── README.md │ ├── around-advices.md │ ├── post-advices.md │ └── pre-advices.md ├── model-integration │ ├── README.md │ └── model-data-binding.md ├── relocating.md ├── rendering-data.md ├── sending-files.md ├── setting-views.md ├── validation.md └── viewlets-reusable-events.md ├── interceptors ├── README.md ├── core-interception-points │ ├── README.md │ ├── application-life-cycle-events.md │ ├── cachebox-events.md │ ├── layout-view-events.md │ ├── module-events.md │ └── object-creating-events.md ├── custom-events │ ├── README.md │ ├── announcing-interceptions.md │ ├── configuration-registration.md │ ├── listening.md │ └── programmatic-registration.md ├── dynamic-registration.md ├── how-do-they-work │ ├── README.md │ └── conventions.md ├── interceptor-asynchronicity │ ├── README.md │ ├── async-announcements.md │ ├── async-listeners-no-join.md │ ├── async-listeners-with-join.md │ └── asynchronous-annotations.md ├── interceptor-declaration.md ├── interceptor-output-buffer.md ├── interceptor-registration.md ├── reporting-methods.md ├── restricting-execution.md └── unregistering-interceptors.md ├── layouts-and-views ├── README.md ├── coldbox-elixir.md ├── helpers-udfs.md ├── implicit-layout-view-declarations.md ├── layouts │ ├── README.md │ ├── basic-layouts.md │ ├── default-layout.md │ ├── layout-events.md │ ├── layout-helpers.md │ ├── layouts-from-a-module.md │ ├── nested-layouts.md │ └── overriding-layouts.md └── views │ ├── README.md │ ├── rendering-collections.md │ ├── rendering-external-views.md │ ├── rendering-views.md │ ├── rendering-with-local-variables.md │ ├── view-caching.md │ ├── view-events.md │ └── view-helpers.md ├── models ├── README.md ├── coding-activeentity-style │ ├── README.md │ ├── contact.cfc.md │ ├── contacts-handler.md │ ├── orm.md │ └── views.md ├── coding-orm-scaffolding │ ├── README.md │ ├── contacts.cfc.md │ ├── orm.md │ └── scaffold.md ├── coding-solo-style │ ├── README.md │ ├── contact.cfc.md │ ├── contactdao.cfc.md │ ├── contacts-handler.md │ ├── contactservice.cfc.md │ └── datasource.md ├── coding-virtual-service-layer │ ├── README.md │ ├── contacts-handler.md │ ├── contacts.cfc.md │ ├── orm.md │ └── views.md ├── conventions-location.md ├── domain-modeling │ ├── README.md │ ├── book.md │ ├── data-layers.md │ └── service-layer.md ├── injection-dsl │ ├── README.md │ ├── cachebox-namespace.md │ ├── coldbox-namespace.md │ ├── entityservice-namespace.md │ ├── executor-namespace.md │ ├── java-namespace.md │ ├── logbox-namespace.md │ ├── model-object-namespace.md │ ├── provider-namespace.md │ └── wirebox-namespace.md ├── object-scopes.md ├── super-type-usage-methods.md └── wirebox-binder.md ├── request-context.md └── routing ├── README.md ├── application-router.md ├── building-routable-links.md ├── html-base-tag.md ├── http-method-spoofing.md ├── pathinfo-providers.md ├── requirements ├── README.md └── rewrite-rules.md ├── restful-extension-detection.md └── routing-dsl ├── README.md ├── named-routes.md ├── pattern-placeholders.md ├── resourceful-routes.md ├── routing-by-convention.md ├── routing-groups.md ├── routing-methods.md └── routing-namespaces.md /.gitbook/assets/AsyncScheduler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/AsyncScheduler.png -------------------------------------------------------------------------------- /.gitbook/assets/Bootstrapper.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/Bootstrapper.jpg -------------------------------------------------------------------------------- /.gitbook/assets/BugsCostMoney.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/BugsCostMoney.png -------------------------------------------------------------------------------- /.gitbook/assets/CacheBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/CacheBox.png -------------------------------------------------------------------------------- /.gitbook/assets/CacheExample_cache_snapshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/CacheExample_cache_snapshot.png -------------------------------------------------------------------------------- /.gitbook/assets/ColdBox Virtual App
Life-Cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ColdBox Virtual App
Life-Cycle.png -------------------------------------------------------------------------------- /.gitbook/assets/ColdBoxLifecycles.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ColdBoxLifecycles.jpg -------------------------------------------------------------------------------- /.gitbook/assets/ColdBoxLifecyclesProxy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ColdBoxLifecyclesProxy.jpg -------------------------------------------------------------------------------- /.gitbook/assets/ColdBoxLogo2015_300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ColdBoxLogo2015_300.png -------------------------------------------------------------------------------- /.gitbook/assets/ColdBoxMajorClasses.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ColdBoxMajorClasses.jpg -------------------------------------------------------------------------------- /.gitbook/assets/ColdBoxProxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ColdBoxProxy.png -------------------------------------------------------------------------------- /.gitbook/assets/ColdBoxScheduler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ColdBoxScheduler.png -------------------------------------------------------------------------------- /.gitbook/assets/ColdBoxSimpleMVC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ColdBoxSimpleMVC.png -------------------------------------------------------------------------------- /.gitbook/assets/ColdBoxTestingClasses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ColdBoxTestingClasses.png -------------------------------------------------------------------------------- /.gitbook/assets/Coldbox-cfc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/Coldbox-cfc.jpg -------------------------------------------------------------------------------- /.gitbook/assets/CommandBoxLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/CommandBoxLogo.png -------------------------------------------------------------------------------- /.gitbook/assets/ControllerLayer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ControllerLayer.jpg -------------------------------------------------------------------------------- /.gitbook/assets/ControllerWithSettingStructures.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ControllerWithSettingStructures.jpg -------------------------------------------------------------------------------- /.gitbook/assets/DecoratorPattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/DecoratorPattern.png -------------------------------------------------------------------------------- /.gitbook/assets/EventCachingFlow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/EventCachingFlow.jpg -------------------------------------------------------------------------------- /.gitbook/assets/EventHandlerInjection.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/EventHandlerInjection.jpg -------------------------------------------------------------------------------- /.gitbook/assets/EventHandlerModelRequested.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/EventHandlerModelRequested.jpg -------------------------------------------------------------------------------- /.gitbook/assets/EventHandlers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/EventHandlers.jpg -------------------------------------------------------------------------------- /.gitbook/assets/FlashRAMSequence.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/FlashRAMSequence.jpg -------------------------------------------------------------------------------- /.gitbook/assets/HandlerToTestRelationship.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/HandlerToTestRelationship.png -------------------------------------------------------------------------------- /.gitbook/assets/InterceptorChain.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/InterceptorChain.gif -------------------------------------------------------------------------------- /.gitbook/assets/LayoutViewCombinations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/LayoutViewCombinations.png -------------------------------------------------------------------------------- /.gitbook/assets/LogBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/LogBox.png -------------------------------------------------------------------------------- /.gitbook/assets/MVC (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/MVC (1).png -------------------------------------------------------------------------------- /.gitbook/assets/MVC+.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/MVC+.png -------------------------------------------------------------------------------- /.gitbook/assets/MVC+ORM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/MVC+ORM.png -------------------------------------------------------------------------------- /.gitbook/assets/MVC+objects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/MVC+objects.png -------------------------------------------------------------------------------- /.gitbook/assets/MVC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/MVC.png -------------------------------------------------------------------------------- /.gitbook/assets/ModuleConfig.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ModuleConfig.jpg -------------------------------------------------------------------------------- /.gitbook/assets/Modules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/Modules.png -------------------------------------------------------------------------------- /.gitbook/assets/ModulesActivation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ModulesActivation.jpg -------------------------------------------------------------------------------- /.gitbook/assets/ModulesLayoutLookupFalse.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ModulesLayoutLookupFalse.jpg -------------------------------------------------------------------------------- /.gitbook/assets/ModulesLayoutLookupTrue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ModulesLayoutLookupTrue.jpg -------------------------------------------------------------------------------- /.gitbook/assets/ModulesLifecycle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ModulesLifecycle.jpg -------------------------------------------------------------------------------- /.gitbook/assets/ModulesRegistration.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ModulesRegistration.jpg -------------------------------------------------------------------------------- /.gitbook/assets/ModulesUnload.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ModulesUnload.jpg -------------------------------------------------------------------------------- /.gitbook/assets/ModulesViewLookupFalse.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ModulesViewLookupFalse.jpg -------------------------------------------------------------------------------- /.gitbook/assets/ModulesViewLookupTrue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ModulesViewLookupTrue.jpg -------------------------------------------------------------------------------- /.gitbook/assets/New Logging Queues.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/New Logging Queues.png -------------------------------------------------------------------------------- /.gitbook/assets/RequestContextDecorator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/RequestContextDecorator.png -------------------------------------------------------------------------------- /.gitbook/assets/Screen Shot 2020-08-05 at 2.41.20 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/Screen Shot 2020-08-05 at 2.41.20 PM.png -------------------------------------------------------------------------------- /.gitbook/assets/Screen Shot 2020-12-16 at 5.58.20 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/Screen Shot 2020-12-16 at 5.58.20 PM.png -------------------------------------------------------------------------------- /.gitbook/assets/ServiceLayers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ServiceLayers.jpg -------------------------------------------------------------------------------- /.gitbook/assets/TestingClasses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/TestingClasses.png -------------------------------------------------------------------------------- /.gitbook/assets/WireBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/WireBox.png -------------------------------------------------------------------------------- /.gitbook/assets/app_template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/app_template.png -------------------------------------------------------------------------------- /.gitbook/assets/async-programming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/async-programming.png -------------------------------------------------------------------------------- /.gitbook/assets/blog-ColdBox67.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/blog-ColdBox67.png -------------------------------------------------------------------------------- /.gitbook/assets/blog-ColdBox68.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/blog-ColdBox68.png -------------------------------------------------------------------------------- /.gitbook/assets/cachedExecutor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/cachedExecutor.png -------------------------------------------------------------------------------- /.gitbook/assets/cachemonitor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/cachemonitor.jpg -------------------------------------------------------------------------------- /.gitbook/assets/coldbox-7-0-0-release.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/coldbox-7-0-0-release.png -------------------------------------------------------------------------------- /.gitbook/assets/coldbox-7-1-0-release.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/coldbox-7-1-0-release.jpg -------------------------------------------------------------------------------- /.gitbook/assets/coldbox-7-2-0-release.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/coldbox-7-2-0-release.jpg -------------------------------------------------------------------------------- /.gitbook/assets/coldbox-async-packages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/coldbox-async-packages.png -------------------------------------------------------------------------------- /.gitbook/assets/coldbox-engine-support-2021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/coldbox-engine-support-2021.png -------------------------------------------------------------------------------- /.gitbook/assets/coldbox-engine-support.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/coldbox-engine-support.jpeg -------------------------------------------------------------------------------- /.gitbook/assets/coldbox-engine-support.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/coldbox-engine-support.png -------------------------------------------------------------------------------- /.gitbook/assets/coldbox-family.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/coldbox-family.png -------------------------------------------------------------------------------- /.gitbook/assets/coldbox-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/coldbox-logo.png -------------------------------------------------------------------------------- /.gitbook/assets/coldbox-vegas-training-october-2022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/coldbox-vegas-training-october-2022.png -------------------------------------------------------------------------------- /.gitbook/assets/coldbox6.2-async-tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/coldbox6.2-async-tests.png -------------------------------------------------------------------------------- /.gitbook/assets/coldboxlogo2015_300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/coldboxlogo2015_300.png -------------------------------------------------------------------------------- /.gitbook/assets/commandbox-terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/commandbox-terminal.png -------------------------------------------------------------------------------- /.gitbook/assets/commandbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/commandbox.png -------------------------------------------------------------------------------- /.gitbook/assets/eventdriven.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/eventdriven.jpg -------------------------------------------------------------------------------- /.gitbook/assets/eventhandler-around.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/eventhandler-around.jpg -------------------------------------------------------------------------------- /.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1) (1) (1) (1) (1) (1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1) (1) (1) (1) (1) (1).jpg -------------------------------------------------------------------------------- /.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1) (1) (1) (1) (1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1) (1) (1) (1) (1).jpg -------------------------------------------------------------------------------- /.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1) (1) (1) (1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1) (1) (1) (1).jpg -------------------------------------------------------------------------------- /.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1) (1) (1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1) (1) (1).jpg -------------------------------------------------------------------------------- /.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1) (1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1) (1).jpg -------------------------------------------------------------------------------- /.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1).jpg -------------------------------------------------------------------------------- /.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (2).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (2).jpg -------------------------------------------------------------------------------- /.gitbook/assets/eventhandler-prepost (2) (2) (2) (1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/eventhandler-prepost (2) (2) (2) (1).jpg -------------------------------------------------------------------------------- /.gitbook/assets/fixedexecutor (1) (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/fixedexecutor (1) (1).png -------------------------------------------------------------------------------- /.gitbook/assets/fixedexecutor (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/fixedexecutor (1).png -------------------------------------------------------------------------------- /.gitbook/assets/fusion-reactor-profiler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/fusion-reactor-profiler.png -------------------------------------------------------------------------------- /.gitbook/assets/handlertotestrelationship.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/handlertotestrelationship.png -------------------------------------------------------------------------------- /.gitbook/assets/image (1) (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/image (1) (1).png -------------------------------------------------------------------------------- /.gitbook/assets/image (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/image (1).png -------------------------------------------------------------------------------- /.gitbook/assets/image (2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/image (2).png -------------------------------------------------------------------------------- /.gitbook/assets/image (3) (1) (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/image (3) (1) (1).png -------------------------------------------------------------------------------- /.gitbook/assets/image (3) (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/image (3) (1).png -------------------------------------------------------------------------------- /.gitbook/assets/image (3).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/image (3).png -------------------------------------------------------------------------------- /.gitbook/assets/image (4) (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/image (4) (1).png -------------------------------------------------------------------------------- /.gitbook/assets/image (4).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/image (4).png -------------------------------------------------------------------------------- /.gitbook/assets/image (5).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/image (5).png -------------------------------------------------------------------------------- /.gitbook/assets/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/image.png -------------------------------------------------------------------------------- /.gitbook/assets/logo-gradient-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/logo-gradient-dark.png -------------------------------------------------------------------------------- /.gitbook/assets/luis-majano-profile-small.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/luis-majano-profile-small.jpeg -------------------------------------------------------------------------------- /.gitbook/assets/luis-majano-profile.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/luis-majano-profile.jpeg -------------------------------------------------------------------------------- /.gitbook/assets/luis-majano-small.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/luis-majano-small.jpeg -------------------------------------------------------------------------------- /.gitbook/assets/luismajano.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/luismajano.jpg -------------------------------------------------------------------------------- /.gitbook/assets/modelguide_book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/modelguide_book.png -------------------------------------------------------------------------------- /.gitbook/assets/modelguide_bookservice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/modelguide_bookservice.png -------------------------------------------------------------------------------- /.gitbook/assets/mvc-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/mvc-overview.png -------------------------------------------------------------------------------- /.gitbook/assets/ortus-community-square-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ortus-community-square-small.png -------------------------------------------------------------------------------- /.gitbook/assets/ortussolutions_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/ortussolutions_button.png -------------------------------------------------------------------------------- /.gitbook/assets/overview_testing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/overview_testing.png -------------------------------------------------------------------------------- /.gitbook/assets/project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/project.png -------------------------------------------------------------------------------- /.gitbook/assets/request-lifecycle (1) (1) (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/request-lifecycle (1) (1) (1).png -------------------------------------------------------------------------------- /.gitbook/assets/request-lifecycle (1) (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/request-lifecycle (1) (1).png -------------------------------------------------------------------------------- /.gitbook/assets/requestcollectiondatabus (1) (1) (1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/requestcollectiondatabus (1) (1) (1).jpg -------------------------------------------------------------------------------- /.gitbook/assets/requestcollectiondatabus (1) (1).jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/requestcollectiondatabus (1) (1).jpg -------------------------------------------------------------------------------- /.gitbook/assets/resourceful_routes.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/resourceful_routes.PNG -------------------------------------------------------------------------------- /.gitbook/assets/resthandler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/resthandler.png -------------------------------------------------------------------------------- /.gitbook/assets/route-record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/route-record.png -------------------------------------------------------------------------------- /.gitbook/assets/runnables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/runnables.png -------------------------------------------------------------------------------- /.gitbook/assets/scheduledExecutor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/scheduledExecutor.png -------------------------------------------------------------------------------- /.gitbook/assets/shalom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/shalom.jpg -------------------------------------------------------------------------------- /.gitbook/assets/simplemodelclassdiagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/simplemodelclassdiagram.png -------------------------------------------------------------------------------- /.gitbook/assets/singleThreadExecutor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/singleThreadExecutor.png -------------------------------------------------------------------------------- /.gitbook/assets/singleton-renderer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/singleton-renderer.png -------------------------------------------------------------------------------- /.gitbook/assets/space-ninja200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/space-ninja200.png -------------------------------------------------------------------------------- /.gitbook/assets/spaghetti.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/spaghetti.png -------------------------------------------------------------------------------- /.gitbook/assets/tasks-with-and-without-overlaps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/tasks-with-and-without-overlaps.png -------------------------------------------------------------------------------- /.gitbook/assets/tasks-with-no-overlaps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/tasks-with-no-overlaps.png -------------------------------------------------------------------------------- /.gitbook/assets/template-tests-commandbox-runner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/template-tests-commandbox-runner.png -------------------------------------------------------------------------------- /.gitbook/assets/template-tests-runner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/template-tests-runner.png -------------------------------------------------------------------------------- /.gitbook/assets/testharness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/testharness.png -------------------------------------------------------------------------------- /.gitbook/assets/testing-lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/testing-lifecycle.png -------------------------------------------------------------------------------- /.gitbook/assets/timermonitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/timermonitor.png -------------------------------------------------------------------------------- /.gitbook/assets/tracer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/tracer.png -------------------------------------------------------------------------------- /.gitbook/assets/wirebox-transient-cache.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ortus-docs/coldbox-docs/a298eee958a8d6e5a5618ac79f92345f5ee7478b/.gitbook/assets/wirebox-transient-cache.png -------------------------------------------------------------------------------- /digging-deeper/coldbox-proxy/README.md: -------------------------------------------------------------------------------- 1 | # ColdBox Proxy 2 | 3 | ![](../../.gitbook/assets/ColdBoxProxy.png) 4 | 5 | The ColdBox proxy enables remote applications or technologies like Flex, AIR, SOAP WebServices, Event Gateways, ColdFusion RESTful Webservices to communicate with ColdBox and provide an event driven model framework for those applications or for it to act as an enhanced service layer. 6 | 7 | **The one key feature here, is that ColdBox morphs into a remote event-driven framework and no longer an MVC framework that produces HTML.** 8 | -------------------------------------------------------------------------------- /digging-deeper/coldbox-proxy/caveats-and-gotchas.md: -------------------------------------------------------------------------------- 1 | # Caveats & Gotchas 2 | 3 | The most important gotchas in using the ColdBox proxy for remoting or even event gateways is pathing. Paths are totally different if you are using `expandPath()` or per-application mappings. Per-Application mappings can sometimes be a hassle for `onSessionEnd()`. So always be careful when setting up your paths and configurations for remoting. Try to always have the correct paths assigned and tested. 4 | -------------------------------------------------------------------------------- /digging-deeper/coldbox-proxy/proxy-events.md: -------------------------------------------------------------------------------- 1 | # Proxy Events 2 | 3 | The ColdBox Proxy also has a different life cycle than traditional MVC. All of a request's interception points fire with one addition: `preProxyResults`. This event fires right before the proxy returns results back to proxies. This is a great way to do transformations, logging, etc. 4 | 5 | ```javascript 6 | component{ 7 | 8 | function preProxyResults(event, interceptData){ 9 | log.debug("Proxy request finalized: ", interceptData.proxyResults ); 10 | } 11 | 12 | } 13 | ``` 14 | -------------------------------------------------------------------------------- /digging-deeper/coldbox-proxy/standard-return-types.md: -------------------------------------------------------------------------------- 1 | # Standard Return Types 2 | 3 | The `ColdBox.cfc` has one setting that affects proxy operation: 4 | 5 | * `ProxyReturnCollection` : This boolean setting determines if the proxy should return what the event handlers return or just return the request collection structure every time a `process()` method is called. This can be a very useful setting, if you don't even want to return any data from the handlers (via the `process()` method). The framework will just always return the request collection structure back to the proxy caller. By default, the framework has this setting turned to **false** so you can have more control and flexibility. 6 | 7 | ```javascript 8 | coldbox.proxyReturnCollection = true; 9 | ``` 10 | -------------------------------------------------------------------------------- /digging-deeper/coldbox-proxy/the-event-handlers/README.md: -------------------------------------------------------------------------------- 1 | # The Event Handlers 2 | 3 | The event handlers that you will produce for remote interaction are exactly the same as your other handlers, with the exception that they have a return type and return data back to the caller; our proxies. Then our proxies can strong type the return data elements: 4 | 5 | **Handler:** 6 | 7 | ```javascript 8 | function getCacheKeys(event,rc,prc){ 9 | return getCache( rc.cacheProvider ).getKeys(); 10 | } 11 | 12 | function listUsers(event,rc,prc){ 13 | prc.data = userService.list(); 14 | 15 | if( event.isProxyRequest() ){ 16 | return prc.data; 17 | } 18 | 19 | event.setView("users/listUsers"); 20 | } 21 | ``` 22 | 23 | > **Hint** The request context has a method called `isProxyRequest()` which tells the application if the request is coming from a ColdBox proxy. 24 | 25 | **Proxy:** 26 | 27 | ```javascript 28 | array function getCachekEys(string cacheProvider='default'){ 29 | arguments.event = "proxy.getCacheKeys"; 30 | return process(argumentCollection=arguments); 31 | } 32 | 33 | string function getUsersJSON(){ 34 | arguments.event = "proxy.listUsers"; 35 | return serializeJSON( process(argumentCollection=arguments) ); 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /digging-deeper/coldbox-proxy/the-event-handlers/distinguishing-request-types.md: -------------------------------------------------------------------------------- 1 | # Distinguishing Request Types 2 | 3 | Now, what if you want to distinguish between a normal request and a proxy request? Well, the request context object, most commonly known as the event object has a method called: 4 | 5 | * `isProxyRequest` : This boolean method determines what type of request is being executed. 6 | 7 | ```javascript 8 | function listUsers(event,rc,prc){ 9 | prc.data = userService.list(); 10 | 11 | if( event.isProxyRequest() ){ 12 | return prc.data; 13 | } 14 | 15 | event.setView("users/listUsers"); 16 | } 17 | ``` 18 | -------------------------------------------------------------------------------- /digging-deeper/coldbox-proxy/the-event-handlers/renderdata.md: -------------------------------------------------------------------------------- 1 | # RenderData() 2 | 3 | The ColdBox Proxy also has the ability to use the request context's `renderData()` method. So you can build a system that just uses this functionality to transform data into multiple requests. Even have the ability for the same handler to respond to REST/SOAP and MVC all in one method: 4 | 5 | **Event Handler:** 6 | 7 | ```javascript 8 | function list(event,rc,prc){ 9 | prc.users = userService.list(); 10 | event.renderData( data=prc.users, formats="xml,json,html" ); 11 | } 12 | ``` 13 | 14 | **Proxy:** 15 | 16 | ```javascript 17 | string function getUsers(string format="json"){ 18 | arguments.event = "users.list"; 19 | return process(argumentCollection=arguments); 20 | } 21 | ``` 22 | 23 | This handler can now respond to HTML requests, SOAP requests, Flex/Air Requests and even RESTFul requests. How about that! 24 | -------------------------------------------------------------------------------- /digging-deeper/flash-ram/README.md: -------------------------------------------------------------------------------- 1 | # Flash RAM 2 | 3 | The purpose of the Flash RAM is to allow variables to be persisted seamlessly from one request and be picked up in a subsequent request(s) by the same user. This allows you to hide implementation variables and create web flows or conversations in your ColdBox applications. So why not just use session or client variables? Well, most developers forget to clean them up and sometimes they just end up overtaking huge amounts of RAM and no clean cut definition is found for them. With Flash RAM, you have the facility already provided to you in an abstract and encapsulated format. This way, if you need to change your flows storage scope from session to client scope, the change is seamless and painless. 4 | 5 | ![](../../.gitbook/assets/FlashRAMSequence.jpg) 6 | 7 | Every handler, plugin, interceptor, layout and view has a flash object in their variables scope already configured for usage. The entire flash RAM capabilities are encapsulated in a flash object that you can use in your entire ColdBox code. Not only that, but the ColdBox Flash object is based on an interface and you can build your own Flash RAM implementations very easily. It is extremely flexible to work on a concept of a Flash RAM object than on a storage scope directly. So future changes are easily done at the configuration level. 8 | 9 | ![](../../.gitbook/assets/ColdBoxMajorClasses.jpg) 10 | 11 | Our Flash Scope also can help you maintain flows or conversations between requests by using the `discard()` and `keep()` methods. This will continue to expand in our 3.X releases as we build our own conversations DSL to define programmatically wizard like or complex web conversations. Also, the ColdBox Flash RAM has the capability to not only maintain this persistence scope but it also allows you to seamlessly re-inflate these variables into the request collection or private request collection, both or none at all. 12 | -------------------------------------------------------------------------------- /digging-deeper/recipes/README.md: -------------------------------------------------------------------------------- 1 | # Recipes 2 | 3 | A collection of useful recipes for the ColdBox Framework. 4 | -------------------------------------------------------------------------------- /digging-deeper/recipes/application-templates.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: The best way to get started with ColdBox 3 | --- 4 | 5 | # Application Templates 6 | 7 | The best way to get started with ColdBox is with our application templates that you can find here: [coldbox-templates](https://github.com/coldbox-templates). We have a curated collection of starter templates to get you kicking the tires quickly. You will do so via the `coldbox create app` command in the CLI: 8 | 9 | {% embed url="https://github.com/coldbox-templates" %} 10 | github.com/coldbox-templates 11 | {% endembed %} 12 | 13 | ```bash 14 | coldbox create app help 15 | ``` 16 | 17 | Here is a listing of the latest supported templates: 18 | 19 |
TemplateSlugDescription
DefaultdefaultThe default ColdBox application template
ElixirelixirThe default template with ColdBox elixir support for asset pipelines
Modern (experimental)modernA fresh new approach to ColdBox applications that are non-root based. Still experimental
RestrestA base REST API using ColdBox
Rest HMVCrest-hmvcAn HMVC REST API using modules
Super SimplesupersimpleBarebones conventions baby!
20 | 21 | 22 | 23 | ## CommandBox Integration 24 | 25 | The `coldbox create app` command has integration to our application templates via the `skeleton` argument. This can be the name of each of the templates in our repositories or you can use the following alternatives: 26 | 27 | * A name of a ForgeBox entry: `cbtemplate-advanced-script,cbtemplate-simple` 28 | * A Github shortcut: `github-username/repo` 29 | * An HTTP/S URL to a zip file containing a template: [http://myapptemplates.com/template.zip](http://myapptemplates.com/template.zip) 30 | * A folder containing a template: `/opt/shared/templates/my-template` 31 | * A zip file containing the template: `/opt/shared/templates/my-template.zip` 32 | -------------------------------------------------------------------------------- /digging-deeper/recipes/clearing-the-view-cache.md: -------------------------------------------------------------------------------- 1 | # Clearing the View Cache 2 | 3 | ## Introduction 4 | 5 | If you use any of the view partial caching mechanisms in Coldbox either through `setView()` or`view()` you might be asking yourself: 6 | 7 | > Is there an easy, programmatic way to remove a specific element from the view cache? 8 | 9 | The answer is, of course! All view and event caching occurs in a cache provider called template and you can retrieve it like so from your handlers, layouts, views, plugins and interceptors: 10 | 11 | ```javascript 12 | var cache = cachebox.getCache("template"); 13 | ``` 14 | 15 | You can also use the WireBox injection DSL 16 | 17 | ```javascript 18 | property name="cache" inject="cachebox:template" 19 | ``` 20 | 21 | ## Clearing methods 22 | 23 | There are a few methods that will help you clear views: 24 | 25 | * `clearView(viewSnippet)` - Clear views with a snippet 26 | * `clearAllViews(async)` - Clear all views 27 | * `clearViewMulti(viewSnippets)` - Clear multiple view snippets with a list or array of snippets 28 | 29 | ```javascript 30 | getCache( "template" ).clearView('home'); 31 | ``` 32 | 33 | Very easy! Just send in what you need and it will be purged. 34 | -------------------------------------------------------------------------------- /digging-deeper/recipes/debugging-coldbox-apps.md: -------------------------------------------------------------------------------- 1 | # Debugging ColdBox Apps 2 | 3 | We have a special module just for helping you monitor and debug ColdBox applications. To install, fire up CommandBox and install it as a dependency in your application. 4 | 5 | ## CbDebugger Requirements 6 | 7 | * Hibernate extension (on Lucee) 8 | * ORM package (on ACF 2021) 9 | 10 | ```bash 11 | install cbdebugger --saveDev 12 | ``` 13 | 14 | Remember that this module is for development so use the `--saveDev` flag. This will install the ColdBox Debugger module for you, which will attach a debugger to the end of the request and give you lots of flexibility. Please read the instructions here in order to spice it up as you see fit: [https://github.com/coldbox-modules/cbdebugger](https://github.com/coldbox-modules/cbdebugger) 15 | 16 | ![](../../.gitbook/assets/cachemonitor.jpg) 17 | -------------------------------------------------------------------------------- /for-newbies/60-minute-quick-start/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: A 60 minute guide to start working with ColdBox 3 | --- 4 | 5 | # 60 Minute Quick Start 6 | 7 | This guide has been designed to get you started with ColdBox in fewer than 60 minutes. We will take you by the hand and help you build a RESTFul application in 60 minutes or less. After you complete this guide, we encourage you to move on to the [Getting Started Guide](../../getting-started/getting-started-guide.md) and then to the other guides in this book. 8 | 9 | You can find the source code of this quickstart here: [https://github.com/coldbox-samples/60-minute-quickstart](https://github.com/coldbox-samples/60-minute-quickstart) 10 | 11 | {% embed url="https://github.com/coldbox-samples/60-minute-quickstart" %} 12 | 13 | ## Requirements 14 | 15 | * Please make sure you download and install the latest [CommandBox CLI](https://www.ortussolutions.com/products/commandbox). We will show you how in the [Installing ColdBox section](installing-coldbox.md). 16 | * Grab a cup of coffee or tea 17 | * Get comfortable 18 | 19 | ## Need Help? 20 | 21 | ![](../../.gitbook/assets/ortus-community-square-small.png) 22 | 23 | The Ortus Community is the way to get any help for our entire platform and modules: [https://community.ortussolutions.com](https://community.ortussolutions.com) 24 | -------------------------------------------------------------------------------- /for-newbies/60-minute-quick-start/next-steps.md: -------------------------------------------------------------------------------- 1 | # Next Steps 2 | 3 | Congratulations! Did you finish this guide in less than 60 minutes? If you did, please leave us some great feedback below. If you didn't, please tell us why; we would love to improve our guides. 4 | 5 | You can now move on to the next level in becoming a ColdBox Guru! Choose your path below: 6 | 7 | * [Learn about HMVC via ColdBox Modules](../../getting-started/configuration/coldbox.cfc/configuration-directives/modules.md) 8 | * [Learn about Dependency Injection](https://wirebox.ortusbooks.com) 9 | * [Learn about Caching](https://cachebox.ortusbooks.com) 10 | * [Learn about Logging](https://logbox.ortusbooks.com) 11 | * [Learn about Testing](https://testbox.ortusbooks.com) 12 | 13 | ### Getting Help 14 | 15 | If you run into issues or have questions, please jump on our [community](https://community.ortussolutions.com/c/communities/coldbox/13) forum or our [Slack team](https://boxteam.ortussolutions.com) and ask away. 16 | 17 | ColdBox is Professional Open Source under the Apache 2.0 license. We'd love to have your help with the product. 18 | -------------------------------------------------------------------------------- /getting-started/configuration/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Learn how to configure ColdBox according to your needs beyond the conventions. 3 | --- 4 | 5 | # Configuration 6 | 7 | In this area we will learn how to configure ColdBox programmatically via the `config/ColdBox.cfc` file. Most of the configurations in ColdBox are pre-set thanks to it's conventions over configuration approach. So the majority of settings are for fine-grained control, third-party modules and more. 8 | 9 | {% hint style="info" %} 10 | ColdBox relies on **conventions** instead of configurations. 11 | {% endhint %} 12 | 13 | {% hint style="danger" %} 14 | If you make changes to any of the main configuration files you will need to re-initialize your application for the settings to take effect. 15 | {% endhint %} 16 | 17 | ## Re-initializing an Application 18 | 19 | Please note that anytime you make any configuration changes or there are things in memory you wish to clear out, you will be using a URL action that will tell the ColdBox [Bootstrapper](bootstrapper-application.cfc.md) to reinitialize the application. This special URL variable is called `fwreinit` and can be any value or a specific password you setup in the [ColdBox configuration directive](coldbox.cfc/configuration-directives/). 20 | 21 | ``` 22 | // reinit with no password 23 | index.cfm?fwreinit=1 24 | 25 | // reinit with password 26 | index.cfm?fwreinit=mypass 27 | ``` 28 | 29 | You can also use CommandBox CLI to reinit your application if you are using its embedded server: 30 | 31 | ```bash 32 | $ coldbox reinit 33 | ``` 34 | -------------------------------------------------------------------------------- /getting-started/configuration/coldbox.cfc/configuration-directives/cachebox.md: -------------------------------------------------------------------------------- 1 | # CacheBox 2 | 3 | The CacheBox structure is based on the [CacheBox declaration DSL](https://cachebox.ortusbooks.com/), and it allows you to customize the caches in your application. Below are the main keys you can fill out, but we recommend you review the CacheBox documentation for further detail. 4 | 5 | ```javascript 6 | //cachebox configuration 7 | cachebox = { 8 | // Location of the configuration CFC for CacheBox 9 | configFile = "config/CacheBox.cfc", 10 | // Scope registration for CacheBox 11 | scopeRegistration = {enabled=true,scope=application,key=cacheBox}, 12 | // Default Cache Configuration 13 | defaultCache = "views", 14 | // Caches Configuration 15 | caches = {} 16 | }; 17 | ``` 18 | 19 | > **Info** : We would recommend you create a `config/CacheBox.cfc` and put all your caching configuration there instead of in the main ColdBox configuration file. This will give you further portability and decoupling. 20 | 21 | ## ConfigFile 22 | 23 | An absolute or relative path to the CacheBox configuration CFC or XML file to use instead of declaring the rest of the keys in this structure. So if you do not define a cacheBox structure, the framework will look for the default value: `config/CacheBox.cfc` and it will load it if found. If not found, it will use the default CacheBox configuration found in `/coldbox/system/web/config/CacheBox.cfc` 24 | 25 | ## ScopeRegistration 26 | 27 | A structure that enables scope registration of the CacheBox factory in either server, cluster, application or session scope. 28 | 29 | ## DefaultCache 30 | 31 | The configuration of the default cache which will have an implicit name of default which is a reserved cache name. It also has a default provider of CacheBox which cannot be changed. 32 | 33 | ## Caches 34 | 35 | A structure where you can create more named caches for usage in your CacheBox factory. 36 | -------------------------------------------------------------------------------- /getting-started/configuration/coldbox.cfc/configuration-directives/conventions.md: -------------------------------------------------------------------------------- 1 | # Conventions 2 | 3 | This element defines custom conventions for your application. By default, the framework has a default set of conventions that you need to adhere too. However, if you would like to implement your own conventions for a specific application, you can use this setting, otherwise do not declare it: 4 | 5 | ```javascript 6 | //Conventions 7 | conventions = { 8 | handlersLocation = "controllers", 9 | viewsLocation = "views", 10 | layoutsLocation = "views", 11 | modelsLocation = "model", 12 | modulesLocation = "modules", 13 | eventAction = "index" 14 | }; 15 | ``` 16 | -------------------------------------------------------------------------------- /getting-started/configuration/coldbox.cfc/configuration-directives/flash.md: -------------------------------------------------------------------------------- 1 | # Flash 2 | 3 | This directive is how you will configure the [Flash RAM](../../../../digging-deeper/flash-ram/) for operation. Below are the configuration keys and their defaults: 4 | 5 | ```javascript 6 | // flash scope configuration 7 | flash = { 8 | // Available scopes are: session,client,cache,mock or your own class path 9 | scope = "session", 10 | // constructor properties for the flash scope implementation 11 | properties = {}, 12 | // automatically inflate flash data into the RC scope at the beginning of a request 13 | inflateToRC = true, 14 | // automatically inflate flash data into the PRC scope at the beginning of a request 15 | inflateToPRC = false, 16 | // automatically purge flash data for you 17 | autoPurge = true, 18 | // automatically save flash scopes at end of a request and on relocations. 19 | autoSave = true 20 | }; 21 | ``` 22 | -------------------------------------------------------------------------------- /getting-started/configuration/coldbox.cfc/configuration-directives/interceptors.md: -------------------------------------------------------------------------------- 1 | # Interceptors 2 | 3 | This is an array of interceptor definitions that you will use to register in your application. The key about this array is that **ORDER** matters. The interceptors will fire in the order that you register them whenever their interception points are announced, so please watch out for this caveat. Each array element is a structure that describes what interceptor to register. 4 | 5 | ```javascript 6 | //Register interceptors as an array, we need order 7 | interceptors = [ 8 | 9 | { 10 | // The CFC instantiation path 11 | class="", 12 | // The alias to register in WireBox, if not defined it uses the name of the CFC 13 | name="", 14 | // A struct of data to configure the interceptor with. 15 | properties={} 16 | } 17 | 18 | { class="mypath.MyInterceptor", 19 | name="MyInterceptor", 20 | properties={useSetterInjection=false} 21 | } 22 | ]; 23 | ``` 24 | 25 | > **Warning** : Important: Order of declaration matters! Also, when declaring multiple instances of the same CFC (interceptor), make sure you use the name attribute in order to distinguish them. If not, only one will be registered (the last one declared). 26 | -------------------------------------------------------------------------------- /getting-started/configuration/coldbox.cfc/configuration-directives/interceptorsettings.md: -------------------------------------------------------------------------------- 1 | # InterceptorSettings 2 | 3 | This structure configures the interceptor service in your application. 4 | 5 | ```javascript 6 | //Interceptor Settings 7 | interceptorSettings = { 8 | throwOnInvalidStates = false, 9 | customInterceptionPoints = "onLogin,onWikiTranslation,onAppClose" 10 | }; 11 | ``` 12 | 13 | ## `throwOnInvalidStates` 14 | 15 | This tells the interceptor service to throw an exception if the state announced for interception is not valid or does not exist. Defaults to **false**. 16 | 17 | ## `customInterceptionPoints` 18 | 19 | This key is a comma delimited list or an array of custom interception points you will be registering for custom announcements in your application. This is the way to provide an observer-observable pattern to your applications. 20 | 21 | > **Info** Please see the [Interceptors](../../../../the-basics/interceptors/) section for more information. 22 | -------------------------------------------------------------------------------- /getting-started/configuration/coldbox.cfc/configuration-directives/layouts.md: -------------------------------------------------------------------------------- 1 | # Layouts 2 | 3 | The layouts array element is used to define implicit associations between layouts and views/folders, this does not mean that you need to register ALL your layouts. This is a convenience for pairing them, we are in a conventions framework remember. 4 | 5 | Before any renderings occur or lookups, the framework will check this array of associations to try and match in what layout a view should be rendered in. It is also used to create aliases for layouts so you can use aliases in your code instead of the real file name and locations. 6 | 7 | ```javascript 8 | //Register Layouts 9 | layouts = [ 10 | { 11 | // The alias of a layout 12 | name="", 13 | // The layout file 14 | file="", 15 | // A list of view names to render within this layout 16 | views="", 17 | // A list of regex names to match a view 18 | folders="" 19 | } 20 | 21 | // Examples 22 | { name="tester",file="Layout.tester.cfm",views="vwLogin,test",folders="tags,pdf/single" }, 23 | { name="login",file="Login.cfm",folders="^admin/security"} 24 | ]; 25 | ``` 26 | -------------------------------------------------------------------------------- /getting-started/configuration/coldbox.cfc/configuration-directives/layoutsettings.md: -------------------------------------------------------------------------------- 1 | # LayoutSettings 2 | 3 | This structure allows you to define a system-wide default layout and view. 4 | 5 | ```javascript 6 | //Layout Settings 7 | layoutSettings = { 8 | // The default layout to use if NOT defined in a request 9 | defaultLayout = "Main", 10 | // The default view to use to render if NOT defined in a request 11 | defaultView = "youForgot" 12 | }; 13 | ``` 14 | 15 | > **Hint** Please remember that the default layout is `Main.cfm` 16 | -------------------------------------------------------------------------------- /getting-started/configuration/coldbox.cfc/configuration-directives/logbox.md: -------------------------------------------------------------------------------- 1 | # LogBox 2 | 3 | The logBox structure is based on the LogBox declaration DSL, see the [LogBox Documentation](https://logbox.ortusbooks.com/) for much more information. 4 | 5 | ```javascript 6 | //LogBox DSL 7 | logBox = { 8 | // The configuration file without fileextension to use for operation, instead of using this structure 9 | configFile = "config/LogBox", 10 | // Appenders 11 | appenders = { 12 | appenderName = { 13 | class="class.to.appender", 14 | layout="class.to.layout", 15 | levelMin=0, 16 | levelMax=4, 17 | properties={ 18 | name = value, 19 | prop2 = value 2 20 | } 21 | }, 22 | // Root Logger 23 | root = {levelMin="FATAL", levelMax="DEBUG", appenders="*"}, 24 | // Granualr Categories 25 | categories = { 26 | "coldbox.system" = { levelMin="FATAL", levelMax="INFO", appenders="*"}, 27 | "model.security" = { levelMax="DEBUG", appenders="console"} 28 | } 29 | // Implicit categories 30 | debug = ["coldbox.system.interceptors"], 31 | info = ["model.class", "model2.class2"], 32 | warn = ["model.class", "model2.class2"], 33 | error = ["model.class", "model2.class2"], 34 | fatal = ["model.class", "model2.class2"], 35 | off = ["model.class", "model2.class2"] 36 | }; 37 | ``` 38 | 39 | > **Info** : If you do not define a logBox DSL structure, the framework will look for the default configuration file `config/LogBox.cfc`. If it does not find it, then it will use the framework's default logging settings. 40 | 41 | **ConfigFile** 42 | 43 | You can use a configuration CFC instead of inline configuration by using this setting. The default value is `config/LogBox.cfc`, so by convention you can just use that location. If no values are defined or no config file exists, the default configuration file is `coldbox/system/web/config/LogBox.cfc`. 44 | -------------------------------------------------------------------------------- /getting-started/configuration/coldbox.cfc/configuration-directives/modules.md: -------------------------------------------------------------------------------- 1 | # Modules 2 | 3 | The modules structure is used to configure the behavior of the [ColdBox Modules](../../../../hmvc/modules/). 4 | 5 | ```javascript 6 | modules = { 7 | // Will auto reload the modules in each request. Great for development but can cause some loading/re-loading issues 8 | autoReload = true, 9 | // An array of modules to load ONLY 10 | include = [], 11 | // An array of modules to EXCLUDE for operation 12 | exclude = [ "paidModule1", "paidModule2" ] 13 | }; 14 | ``` 15 | 16 | > **Danger** Please be very careful when using the `autoReload` flag as module routing can be impaired and thread consistency will also suffer. This is PURELY a development flag that you can use at your own risk. 17 | -------------------------------------------------------------------------------- /getting-started/configuration/coldbox.cfc/configuration-directives/modulesettings.md: -------------------------------------------------------------------------------- 1 | # ModuleSettings 2 | 3 | ## Option 1: Coldbox Config 4 | 5 | This structure within config/Coldbox.cfc is used to house module configurations. Please refer to each module's documentation on how to create the configuration structures. Usually the keys will match the name of the module to be configured. 6 | 7 | ```javascript 8 | component { 9 | 10 | function configure() { 11 | 12 | moduleSettings = { 13 | myModule = { 14 | someSetting = "overridden" 15 | } 16 | }; 17 | } 18 | } 19 | ``` 20 | 21 | ## Option 2: Config Object Override 22 | 23 | Starting in ColdBox 7, you can store module configurations as their own configuration file within the application’s config folder outside of the config/Coldbox.cfc. The naming convention is config/modules/{moduleName}.cfc 24 | 25 | The configuration CFC will have one configure() method that is expected to return a struct of configuration settings as you did before in the moduleSettings 26 | 27 | ``` 28 | component{ 29 | 30 | function configure(){ 31 | return { 32 | key : value 33 | }; 34 | } 35 | 36 | } 37 | ``` 38 | 39 | ### Injections 40 | 41 | Just like a ModuleConfig this configuration override also gets many injections: 42 | 43 | * controller 44 | * coldboxVersion 45 | * appMapping 46 | * moduleMapping 47 | * modulePath 48 | * logBox 49 | * log 50 | * wirebox 51 | * binder 52 | * cachebox 53 | * getJavaSystem 54 | * getSystemSetting 55 | * getSystemProperty 56 | * getEnv 57 | * appRouter 58 | * router 59 | 60 | ### Env Support 61 | 62 | This module configuration object will also inherit the ModuleConfig.cfc behavior that if you create methods with the same name as the environment you are on, it will execute it for you as well. 63 | 64 | ``` 65 | function development( original ){ 66 | // add overides to the original struct 67 | } 68 | ``` 69 | 70 | Then you can change the original struct as you see fit for that environment. 71 | -------------------------------------------------------------------------------- /getting-started/configuration/coldbox.cfc/configuration-directives/settings.md: -------------------------------------------------------------------------------- 1 | # Settings 2 | 3 | These are custom application settings that you can leverage in your application. 4 | 5 | ```javascript 6 | // Custom Settings 7 | settings = { 8 | useSkins = true, 9 | myCoolArray = [1,2,3,4], 10 | skinsPath = "views/skins", 11 | myUtil = createObject("component","#appmapping#.model.util.MyUtility") 12 | }; 13 | ``` 14 | 15 | You can read our [Using Settings](../../using-settings.md) section to discover how to use all the settings in your application. 16 | -------------------------------------------------------------------------------- /getting-started/configuration/coldbox.cfc/configuration-directives/wirebox.md: -------------------------------------------------------------------------------- 1 | # WireBox 2 | 3 | This configuration structure is used to configure the [WireBox](https://wirebox.ortusbooks.com) dependency injection framework embedded in ColdBox. 4 | 5 | ```javascript 6 | // wirebox integration 7 | wirebox = { 8 | binder = 'config.WireBox', 9 | singletonReload = true 10 | }; 11 | ``` 12 | 13 | **binder** 14 | 15 | The location of the WireBox configuration binder to use for the application. If empty, we will use the binder in the `config` folder called by conventions: `WireBox.cfc` 16 | 17 | **singletonReload** 18 | 19 | A great flag for development. If enabled, WireBox will flush its singleton objects on every request so you can develop without any headaches of reloading. 20 | 21 | > **Warning** : This operation can cause some thread issues and it is only meant for development. Use at your own risk. 22 | -------------------------------------------------------------------------------- /getting-started/conventions.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: Discover the major conventions of the ColdBox framework 3 | --- 4 | 5 | # Conventions 6 | 7 | The core conventions delineate the contract between ColdBox and **you** for file/directory locations and more. Below is a table of the core conventions: 8 | 9 | ## Directory/File Conventions 10 | 11 | * **/config** - Where configuration files are stored 12 | * **/Coldbox.cfc** - Your application configuration object (_optional_ ) 13 | * **/CacheBox.cfc** - Your application CacheBox configuration (_optional_ ) 14 | * **/Router.cfc** - Your application URL Router (_optional_ ) 15 | * **/Scheduler.cfc** - Your application global task scheduler (optional) 16 | * **/WireBox.cfc** - Your application WireBox Configuration (_optional_ ) 17 | * **/handlers** - This holds the app's event handlers (controller layer) 18 | * **/includes** - For public assets, helpers and i18n resources 19 | * **/css** - This can hold your CSS (optional) 20 | * **/js** - This can hold your JavaScript (optional) 21 | * **/layouts** - Your HTML layouts (view layer) 22 | * **/models** - This holds your app's CFCs (model layer) 23 | * **/modules** - This holds the CommandBox tracked modules 24 | * **/modules\_app** - This holds your app's modules 25 | * **/tests** - Your test harness, including unit and integration testing 26 | * **/specs** - Where your test bundles go 27 | * **/views** - Your HTML views will go here (view layer) 28 | 29 | ## Execution Conventions 30 | 31 | ColdBox also has several execution conventions. This means that we have a convention or a default for the event, action, and layout to be used if you do not tell it what to use: 32 | 33 |
ConventionDefault ValueDescription
ConventionDefault ValueDescription
Default Eventmain.indexThe default event to execute when no event is specified
Default Actionindex()The default action to execute in an event handler controller if none is specified
Default Layoutlayouts/Main.cfmThe default system layout to use
34 | -------------------------------------------------------------------------------- /hmvc/modules/README.md: -------------------------------------------------------------------------------- 1 | # Modules 2 | 3 | ![](https://github.com/ortus-docs/coldbox-docs/raw/master/.gitbook/assets/modules.png) 4 | 5 | ColdBox Modules are self-contained subsets of a ColdBox application that can be dropped in to any ColdBox application and become alive as part of the host application. They will bring re-usability and extensibility to any ColdBox application, as now you can break them down further into a collection of modules instead of monolithic approaches. CommandBox will also help you manage, install, track and uninstall modules as part of your development workflow. 6 | 7 | This concept of modularization has been around in software design for a long time as it is always essential to partition a system into manageable modules or parts. 8 | 9 | > "In structured design and data-driven design, a module is a generic term used to describe a named and addressable group of program statements" by Craig Borysowich (Chief Technology Tactician) 10 | 11 | The key to the statement is that these modules are named and addressable, which is exactly what ColdBox Modules will offer to your application. So by building an application with a methodology of modules, you will inherently achieve: 12 | 13 | * **Manageability** (i.e., small and simple parts that can be easily understood and worked on) 14 | * **Independence** (i.e., a module can live on its own if necessary and tested outside of its environments, produces very nice low coupling between core and modules) 15 | * **Isolation** (i.e., some modules can be completely isolated and decoupled) 16 | * **Extensibility** (i.e., you can easily extend ANY application by just building on top of the modular architecture) 17 | * **Reusability** (i.e., modules have independence and can therefore be shared and reused) 18 | * **Sanitability** (Yes! That's a word) from the root Sanity 19 | 20 | ColdBox Modules will change the way you approach application development as you can now have a foundation architecture that can scale easily and provide you enough manageability to reduce maintenance and increase development. Such a design means that development, testing and maintenance becomes easier, faster and with a much lower cost. **Welcome to a brave new world!** 21 | -------------------------------------------------------------------------------- /hmvc/modules/layout-and-view-renderings/README.md: -------------------------------------------------------------------------------- 1 | # Layout and View Renderings 2 | 3 | The ColdBox rendering engine has been adapted to support module renderings and also to support multiple discovery algorithms when rendering module layouts and views. When you declare a module you can declare two of its public properties to determine how rendering overrides occur. These properties are: 4 | 5 | | Property | Type | Required | Default | Description | 6 | | ------------------ | ------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | 7 | | viewParentLookup | boolean | false | true | If true, coldbox checks for views in the parent overrides first, then in the module. If false, coldbox checks for views in the module first, then the parent. | 8 | | layoutParentLookup | boolean | false | true | If true, coldbox checks for layouts in the parent overrides first, then in the module. If false, coldbox checks for layouts in the module first, then the parent. | 9 | -------------------------------------------------------------------------------- /hmvc/modules/layout-and-view-renderings/default-module-layout.md: -------------------------------------------------------------------------------- 1 | # Default Module Layout 2 | 3 | You can also implicitly setup a default layout to use when rendering views from the specific module. This only works when you call the `event.setView()` method from your module event handlers. Once called, the framework will discover the default layout to render that view in. You set up the default layout for a module by using the layoutSettings structure in your configuration: 4 | 5 | ```javascript 6 | layoutSettings = { 7 | defaultLayout = "MyLayout.cfm" 8 | }; 9 | ``` 10 | 11 | > **Caution** The set default layout MUST exist in the layouts folder of your module and the declaration must have the `.cfm` extension attached. 12 | -------------------------------------------------------------------------------- /hmvc/modules/layout-and-view-renderings/explicit-module-renderings.md: -------------------------------------------------------------------------------- 1 | # Explicit Module Renderings 2 | 3 | You can also explicitly render layouts or views directly from a module via the Renderer plugin's `layout()` and `view()` methods. These methods now can take an extra argument called module. 4 | 5 | * `layout(layout, view, module)` 6 | * `view(view, cache, cacheTimeout,cacheLastAccessTimeout,cacheSuffix, module)` 7 | 8 | So you can easily pinpoint renderings if needed. 9 | 10 | > **Caution** Please note that whenever these methods are called, the override algorithms ALSO are in effect. So please refer back to the view and layout parent lookup properties in your modules' configuration. 11 | -------------------------------------------------------------------------------- /hmvc/modules/layout-and-view-renderings/overriding-layouts.md: -------------------------------------------------------------------------------- 1 | # Overriding Layouts 2 | 3 | Now, let's say you want to override the layout for a module. Go to the host application's layouts folder and create a folder called `modules` and then a folder according to the module name, in our case `simpleModule`: 4 | 5 | ```javascript 6 | /MyApp 7 | + layouts 8 | + modules 9 | + simpleModule 10 | ``` 11 | 12 | What this does, is create the override structure that you need. So now, you can map 1-1 directly from this overrides folder to the module's layouts folder. So whatever layout you place here that matches 1-1 to the module, the parent will take precedence. Now remember this is because our layouParentLookup property is set to true. If we disable it or set it to false, then the module takes precedence first. If not found in the module, then it goes to the parent or host application and tries to locate the layout. That's it, so if I place a main.cfm layout in my parent structure, the that one will take precedence. 13 | 14 | ```javascript 15 | /MyApp 16 | + layouts 17 | + modules 18 | + simpleModule 19 | + main.cfm 20 | ``` 21 | 22 | These features are great for skinning modules or just overriding view capabilities a-la-carte. So please take note of them as it is very powerful. 23 | -------------------------------------------------------------------------------- /hmvc/modules/layout-and-view-renderings/overriding-views.md: -------------------------------------------------------------------------------- 1 | # Overriding Views 2 | 3 | This tells the framework to render the `simple/index.cfm` view in the module `simpleModule`. However, let's override the view first. Go to the host application's views folder and create a folder called `modules` and then a folder according to the module name, in our case `simpleModule`: 4 | 5 | ```javascript 6 | /MyApp 7 | + views 8 | + modules 9 | + simpleModule 10 | ``` 11 | 12 | What this does, is create the override structure that you need. So now, you can map 1-1 directly from this overrides folder to the module's views folder. So whatever view you place here that matches 1-1 to the module, the parent will take precedence. Now remember this is because our `viewParentLookup` property is set to true. If we disable it or set it to false, then the module takes precedence first. If not found in the module, then it goes to the parent or host application and tries to locate the view. That's it, so if I place a `simple/index.cfm` view in my parent structure, the that one will take precedence. 13 | -------------------------------------------------------------------------------- /hmvc/modules/locations.md: -------------------------------------------------------------------------------- 1 | # Locations 2 | 3 | By convention every ColdBox application will have two folders for modules: 4 | 5 | * **/modules** : Used by CommandBox to place tracked modules. You would usually NOT commit these modules to source control. 6 | * **/modules\_app** : Used for custom non-tracked modules 7 | 8 | ## External Locations 9 | 10 | You can also have more external locations that ColdBox will scan for modules by leveraging the `coldbox.modulesExternalLocation` setting. This setting is an array of locations you want to tell ColdBox to look for modules in your `ColdBox.cfc`. Each array element is the instantiation location which can use ColdFusion mappings or an absolute reference from the root of your application. 11 | 12 | > **Caution** Internally each of those entries will be expanded for you, so please be aware of this. 13 | 14 | ```javascript 15 | coldbox = { 16 | 17 | ... 18 | 19 | modulesExternalLocation = [ "/shared/modules", "/codedepot/modules/customer1" ] 20 | 21 | }; 22 | ``` 23 | 24 | ## Duplicate Names 25 | 26 | You might be asking yourself, what happens if there is another module in the external locations with the same name as in another location? Or even in the conventions? Well, the first one found takes precedence. So if we have a module called `funky` in our conventions folder and also in our external locations, only the one in the conventions will load as it is discovered first. 27 | -------------------------------------------------------------------------------- /hmvc/modules/models.md: -------------------------------------------------------------------------------- 1 | # Models 2 | 3 | When you declare a module and you define a `models` folder then the framework automatically register all models in that folder for you using a namespace of `@moduleName`. This means that all models are registered according to their CFC name plus the namespace. 4 | 5 | > **Info** Internally, ColdBox uses WireBox's `mapDirectory()` to map the entire `models` directory for you. 6 | 7 | Let's say you have a module called `store` and a `OrderService.cfc` inside of the `models` folder. That object will have a WireBox id of `OrderService@store`. 8 | 9 | ```javascript 10 | property name="orderService" inject="OrderService@store"; 11 | ``` 12 | 13 | > **Hint** You can alter this behavior by setting the `this.autoMapModels` configuration setting to **false**. You can also alter the namespace used via the `this.modelNamespace` configuration property. 14 | -------------------------------------------------------------------------------- /hmvc/modules/module-bundles.md: -------------------------------------------------------------------------------- 1 | # Module Bundles 2 | 3 | You can bundle your modules into an organizational folder that has the convention name of `{name}-bundle`. This will allow you to bundle different modules together for organizational purposes only. Great for git ignores. 4 | 5 | ``` 6 | coldbox-bundle 7 | * cbstorages 8 | * cborm 9 | * cbsecurity 10 | ``` 11 | -------------------------------------------------------------------------------- /hmvc/modules/module-cf-mappings.md: -------------------------------------------------------------------------------- 1 | # Module CF Mappings 2 | 3 | Every module can tell ColdBox what ColdFusion mapping to register for it that points to the module root location on disk when deployed. This is a huge feature for portability and the ability to influence the ColdFusion mappings for you via ColdBox. Just create a `this.cfmapping` property in your `ModuleConfig.cfc`: 4 | 5 | ```javascript 6 | this.cfmapping = "cbstore"; 7 | ``` 8 | -------------------------------------------------------------------------------- /hmvc/modules/module-dependencies.md: -------------------------------------------------------------------------------- 1 | # Module Dependencies 2 | 3 | Modules can declare other module dependencies in the `ModuleConfig.cfc` via the `this.dependencies` property. This means that **before** the declared module is activated, the dependencies will be registered and activated **FIRST** and then the declared module will load. 4 | 5 | ```javascript 6 | this.dependencies = [ "javaloader" ]; 7 | ``` 8 | 9 | This means that the `javaloader` module HAS to load and activate first before this module can finish registering and activating. 10 | -------------------------------------------------------------------------------- /hmvc/modules/module-event-executions.md: -------------------------------------------------------------------------------- 1 | # Module Event Executions 2 | 3 | Module event executions are done almost exactly the same way we are used to in our ColdBox applications using event syntax patterns. By now we understand that an event comes in via the URL/FORM or Remotely to the framework and then the framework decides what event to execute. We also know that we can abstract our incoming events by using the ColdBox URL Routing, but at the end of the day, we will always have an `event` variable in the request collection that tells the framework what event to execute. The typical event syntax pattern we have learned is: 4 | 5 | ```javascript 6 | // Pattern 7 | event=[package.]handler[.action] 8 | 9 | // Examples: 10 | event=blog.posts 11 | event=home.index 12 | event=admin.dashboard.index 13 | ``` 14 | 15 | This typical approach maps the event to a package, handler and method combination. With the addition of modules our event syntax pattern now morphs to the following: 16 | 17 | ```javascript 18 | // Pattern 19 | event=[module:][package.]handler[.action] 20 | 21 | // Examples: 22 | event=blog:posts.index 23 | event=cms:page.show 24 | event=admin:dashboard 25 | ``` 26 | 27 | As you can see, we can prefix the event syntax with a module name and then followed by a colon `{module}:`. This is how ColdBox can know to what module to redirect the execution to. You can even execute the `runEvent()` methods and target modules: 28 | 29 | ```javascript 30 | // Execute a viewlet in a module called viewlets: 31 | #runEvent('viewlets:users.dashboard')# 32 | ``` 33 | 34 | > **Hint** Please remember that this is great for securing your applications as the event patterns you can match against with regular expressions will help you tremendously, as you can pinpoint modules directly. 35 | 36 | In summary, the event syntax has been updated to support module executions via the `{module:}` prefix. However, please note that our preference is to abstract URLs and incoming event variables (via FORM/URL) by using ColdBox URL Routing. In the next section we will revise how to make module URL Routings work. 37 | -------------------------------------------------------------------------------- /hmvc/modules/module-helpers.md: -------------------------------------------------------------------------------- 1 | # Module Helpers 2 | 3 | Every module can declare an array of helper templates that contain **methods** that will be added as **global** application helpers. This is a great way to collaborate global functions to the running MVC application. 4 | 5 | This is done via the `this.applicationHelper` directive in your `ModuleConfig.cfc`. This is an array of relative paths in the module that ColdBox will load as mixins. 6 | 7 | ```javascript 8 | this.applicationHelper = [ 9 | "includes/helpers.cfm" 10 | ]; 11 | ``` 12 | 13 | Here is a sample of a `helpers.cfm`: 14 | 15 | ```javascript 16 | 17 | function auth() { 18 | return wirebox.getInstance( "AuthenticationService@cbauth" ); 19 | } 20 | 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /hmvc/modules/module-inception.md: -------------------------------------------------------------------------------- 1 | # Module Inception 2 | 3 | ![](../../.gitbook/assets/Modules.png) 4 | 5 | ColdBox 4 allows you to nest modules within modules up to the Nth degree. You can package a module with other modules that can even contain other modules within them. It really opens a great opportunity for better packaging, delivery and a further break from monolithic applications. To use, just create a `modules` folder in your module and drop the modules there as well. You can also just create a `box.json` in the root of your module and let CommandBox manage your module dependencies. Here is an example of the ColdBox ORM Module: 6 | 7 | ```javascript 8 | { 9 | "name" : "ColdBox ORM Extensions", 10 | "version" : "1.0.3", 11 | "author" : "Luis Majano ", "Curt Gratz ", "Joel Watson " 23 | ], 24 | "dependencies" :{ 25 | "cbvalidation" : "1.0.2" 26 | }, 27 | "ignore":[ 28 | "**/.*", 29 | "tests", 30 | "apidocs", 31 | "*/.md" 32 | ] 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /hmvc/modules/module-layout/changing-the-module-layout.md: -------------------------------------------------------------------------------- 1 | # Changing The Module Layout 2 | 3 | If you are picky and you would like to change the folder layout for your module, you can. This is achieved from within the `ModuleConfig.cfc` by adding a `conventions` structure that will explain to the ColdBox Module engine how to locate and configure your module. 4 | 5 | ```javascript 6 | // Module Conventions 7 | conventions = { 8 | handlersLocation = "handlers", 9 | viewsLocation = "views", 10 | layoutsLocation = "layouts", 11 | modelsLocation = "models" 12 | }; 13 | ``` 14 | -------------------------------------------------------------------------------- /hmvc/modules/module-service/README.md: -------------------------------------------------------------------------------- 1 | # Module Service 2 | 3 | The beauty of ColdBox Modules is that you have an internal module service that you can tap in order to dynamically interact with the ColdBox Modules. This service is available by talking to the main ColdBox controller and calling its `getModuleService()` method or via dependency injection. 4 | 5 | ```javascript 6 | // get module service from handlers, plugins, layouts, interceptors or views. 7 | ms = controller.getModuleService(); 8 | 9 | // You can also inject it via our autowire DSL 10 | property name="moduleService" inject="coldbox:moduleService"; 11 | ``` 12 | -------------------------------------------------------------------------------- /hmvc/modules/module-service/common-methods.md: -------------------------------------------------------------------------------- 1 | # Common Methods 2 | 3 | Here are the most common methods you can use to manage modules: 4 | 5 | * `reloadAll()` : Reload all modules in the application. This clears out all module settings, re-registers from disk, re-configures them and activates them 6 | * `reload(module)` : Target a module reload by name 7 | * `unloadAll()` : Unload all modules 8 | * `unload(module)` : Target a module unload by name 9 | * `registerAllModules()` : Registers all module configurations 10 | * `registerModule(moduleName,[instantiationPath])` : Target a module configuration registration 11 | * `activateAllModules()` : Activate all registered modules 12 | * `activateModule(moduleName)` : Target activate a module that has been registered already 13 | * `getLoadedModules()` : Get an array of loaded module names 14 | * `rebuildModuleRegistry()` : Rescan all the module locations for newly installed modules and rebuild the registry so these modules can be registered and activated. 15 | * `registerAndActivateModule(moduleName,[instantiationPath])` : Register and Activate a new module 16 | 17 | With these methods you can get creative and target the reloading, unloading or loading of specific modules. These methods really open the opportunity to build an abstraction API where you can install modules in your application on the fly and then register and activate them. You can also do the inverse and deactivate modules in a running application. 18 | -------------------------------------------------------------------------------- /hmvc/modules/module-service/loading-a-la-carte-modules.md: -------------------------------------------------------------------------------- 1 | # Loading A-la-carte Modules 2 | 3 | You can also use the same module service methods to load ANY module in ANY ColdFusion reachable location. This is huge for applications that need granular control of loading and unloading of modules. You will do this with our magic method: 4 | 5 | ```javascript 6 | registerAndActivateModule(moduleName,[instantiationpath]) 7 | ``` 8 | 9 | This time, you will pass an instantiation path to the method. This is the dot notation path up to the folder that contains the module. So let's say your module to load is located here: 10 | 11 | ```javascript 12 | /shared 13 | /modules 14 | /Calendar 15 | +ModuleConfig.cfc 16 | ``` 17 | 18 | You will then issue the following: 19 | 20 | ```javascript 21 | controller.getModuleService().registerAndActivateModule('Calendar','shared.modules') 22 | ``` 23 | 24 | > **Caution** The instantiation path does **NOT** include the name of the module on disk as the name is the module name you already pass into the method. 25 | -------------------------------------------------------------------------------- /hmvc/modules/module-service/loading-new-modules.md: -------------------------------------------------------------------------------- 1 | # Loading New Modules 2 | 3 | If you want to load a new module in your application that you have just installed you need to do a series of steps. 4 | 5 | 1. Drop the module in any of the module locations defined or an a-la-carte location 6 | 2. Call `registerAndActivateModule(moduleName,[instantiationPath])` to register and activate the module 7 | 8 | ```javascript 9 | controller.getModuleService().registerAndActivateModule('TaskManager'); 10 | ``` 11 | -------------------------------------------------------------------------------- /hmvc/modules/module-service/module-activation.md: -------------------------------------------------------------------------------- 1 | # Module Activation 2 | 3 | Below you can see a diagram of what happens when modules get activated right after registration: 4 | 5 | ![](../../../.gitbook/assets/ModulesActivation.jpg) 6 | -------------------------------------------------------------------------------- /hmvc/modules/module-service/module-events.md: -------------------------------------------------------------------------------- 1 | # Module Events 2 | 3 | The module service also announces several events or interception points as you saw from the life cycle diagrams. Below are the events announced: 4 | 5 | ## preModuleLoad 6 | 7 | Fired before a module is about to be activated. 8 | 9 | **Data:** 10 | 11 | * `moduleLocation` - The location of the loaded module 12 | * `moduleName` - The name of the module 13 | 14 | ## postModuleLoad 15 | 16 | Fired after a module has been successfully activated 17 | 18 | **Data:** 19 | 20 | * `moduleLocation` - The location of the loaded module 21 | * `moduleName` - The name of the module 22 | * `moduleConfig` - The module configuration structure 23 | 24 | ## preModuleUnload 25 | 26 | Fired before a module is about to be unloaded 27 | 28 | **Data:** 29 | 30 | * `moduleName` - The name of the module 31 | 32 | ## postModuleUnload 33 | 34 | Fired after a module has been unloaded 35 | 36 | **Data:** 37 | 38 | * `moduleName` - The name of the module 39 | -------------------------------------------------------------------------------- /hmvc/modules/module-service/module-lifecycle.md: -------------------------------------------------------------------------------- 1 | # Module Lifecycle 2 | 3 | ![](../../../.gitbook/assets/ModulesLifecycle.jpg) 4 | 5 | However, before we start reviewing the module service methods let's review how modules get loaded in a ColdBox application. Below is a simple bullet point of what happens in your application when it starts up: 6 | 7 | 1. ColdBox main application and configuration loads 8 | 2. ColdBox Cache, Logging and WireBox are created 9 | 3. Module Service calls on `registerAllModules()` to read all the modules in the modules locations (with include/excludes) and start registering their configurations one by one. If the module had parent settings, interception points, datasoures or webservices, these are registered here. 10 | 4. All main application interceptors are loaded and configured 11 | 5. ColdBox is marked as initialized 12 | 6. Module service calls on `activateAllModules()` so it begins activating only the registered modules one by one. This registers the module's SES URL Mappings, model objects, etc 13 | 7. `afterConfigurationLoad` interceptors are fired 14 | -------------------------------------------------------------------------------- /hmvc/modules/module-service/module-registration.md: -------------------------------------------------------------------------------- 1 | # Module Registration 2 | 3 | Below you can see a diagram of what happens when modules get registered: 4 | 5 | ![](../../../.gitbook/assets/ModulesRegistration.jpg) 6 | -------------------------------------------------------------------------------- /hmvc/modules/module-service/module-unloading.md: -------------------------------------------------------------------------------- 1 | # Module Unloading 2 | 3 | Below you can see a diagram of what happens when modules get deactivated and unloaded 4 | 5 | ![](../../../.gitbook/assets/ModulesUnload.jpg) 6 | -------------------------------------------------------------------------------- /hmvc/modules/moduleconfig/README.md: -------------------------------------------------------------------------------- 1 | # ModuleConfig 2 | 3 | The module configuration object: `ModuleConfig.cfc` is the boot code of your module and where you can tell the host application how this module will behave. This component is a simple CFC, no inheritance needed, because it is decorated with methods and variables by ColdBox at runtime. 4 | 5 | The only requirement is that this object MUST exist in the root of the module folder and contain a `configure()` method. This is the way modules are discovered, so if there is no `ModuleConfig.cfc` in the root of that folder inside of the modules folder, the framework skips it. So let's investigate what we need or can do in this component. 6 | 7 | ```javascript 8 | component{ 9 | 10 | function configure(){ 11 | 12 | } 13 | 14 | } 15 | ``` 16 | -------------------------------------------------------------------------------- /hmvc/modules/moduleconfig/environment-control.md: -------------------------------------------------------------------------------- 1 | # Environment Control 2 | 3 | If you are using per-environment control in your parent application via the `ColdBox.cfc`, you can also use that in your Module Configuration object. So the same conventions that are used in the parent configuration can be used in the module; having the name of the environment match a method name in your module config. So if the following environments are declared in your parent configuration file and the **dev** environment is detected, the `dev()` method is called in your configuration object: 4 | 5 | ```javascript 6 | environments = { 7 | dev = "^railo.*,^cf.*,^local.*" 8 | }; 9 | 10 | function dev(){ 11 | // my overrides here 12 | coldbox.handlerCaching = false; 13 | } 14 | ``` 15 | 16 | But if you declare that `dev()` method in your Module Configuration object, it will be called as well **after** your `configure()` method is called: 17 | 18 | ```javascript 19 | function configure(){} 20 | 21 | function dev(){ 22 | // override module settings for dev here. 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /hmvc/modules/moduleconfig/interceptor-events.md: -------------------------------------------------------------------------------- 1 | # Interceptor Events 2 | 3 | The module configuration object is also treated as an Interceptor once it is created and configured. 4 | 5 | ## Life-cycle Events 6 | 7 | There are two life-cycle callback events you can declare in your `ModuleConfig.cfc`: 8 | 9 | * `onLoad()` : Called when the module is loaded and activated 10 | * `onUnLoad()` : Called when the module is unloaded from memory 11 | 12 | This gives you great hooks for you to do bootup and shutdown commands for this specific module. You can build a [ContentBox](http://ortussolutions.com/products/contentbox/) or [Wordpress](http://wordpress.org/) like application very easily all built in to the developing platform. 13 | 14 | ```javascript 15 | function onLoad(){ 16 | // Register some tables in my database and activate some features 17 | controller.getWireBox().getInstance('MyModuleService').activate(); 18 | log.info( 'Module #this.title# loaded correctly' ); 19 | } 20 | 21 | function onUnLoad(){ 22 | // Cleanup some stuff and logit 23 | controller.getWireBox().getInstance('MyModuleService').shutdown(); 24 | 25 | // Log we unloaded 26 | log.info( 'My module unloaded successfully!' ); 27 | } 28 | ``` 29 | 30 | ## Custom Events 31 | 32 | Also, remember that the configuration object itself is an interceptor so you can declare all of the framework's interception points in the configuration object and they will be registered as interceptors. 33 | 34 | ```javascript 35 | function preProcess(event, interceptData){ 36 | // I just intercepted ALL incoming requests to the application 37 | log.info('The event executed is #arguments.event.getCurrentEvent()#'); 38 | } 39 | ``` 40 | 41 | This is a powerful feature, you can create an entire module based on a single CFC and just treat it as an interceptor. So get your brain into gear and let the gas run, you are going for a ride baby! 42 | -------------------------------------------------------------------------------- /hmvc/modules/moduleconfig/the-decorated-variables.md: -------------------------------------------------------------------------------- 1 | # The Decorated Variables 2 | 3 | ![](../../../.gitbook/assets/ModuleConfig.jpg) 4 | 5 | At runtime, the configuration object will be created by ColdBox and decorated with the following private properties (available in the `variables` scope): 6 | 7 | | Property | Description | 8 | | ------------- | ---------------------------------------------------------------------------------------------------------------------- | 9 | | appMapping | The `appMapping` setting of the current host application | 10 | | binder | The WireBox configuration binder object | 11 | | cachebox | A reference to CacheBox | 12 | | controller | A reference to the application's ColdBox Controller | 13 | | log | A pre-configured LogBox Logger object for this specific class object (`coldbox.system.logging.Logger`) | 14 | | logBox | A Reference to LogBox | 15 | | moduleMapping | The `moduleMapping` setting of the current module. This is the path needed in order to instantiate CFCs in the module. | 16 | | modulePath | The absolute path to the current loading module | 17 | | wirebox | A Reference to WireBox | 18 | 19 | You can use any of these private variables to create module settings, load CFCs, add binder mappings, etc. 20 | -------------------------------------------------------------------------------- /hmvc/modules/parent-configuration.md: -------------------------------------------------------------------------------- 1 | # Parent Configuration 2 | 3 | There are a few parent application settings when dealing with modules. In your `ColdBox.cfc` you can have a `modules` structure with some configuration settings. 4 | 5 | ``` 6 | modules = { 7 | // reload and unload modules in every request 8 | // DEPRECATED in coldbox 5 9 | autoReload = false, 10 | // An array or list of the module names that will load ONLY 11 | include = [], 12 | // An array or list of the module names that will be EXCLUDED 13 | exclude = ["paidModule1","paidModule2"] 14 | }; 15 | ``` 16 | -------------------------------------------------------------------------------- /hmvc/modules/request-context-module-methods.md: -------------------------------------------------------------------------------- 1 | # Request Context Module Methods 2 | 3 | The request context object (`event` parameter received in handlers/layouts/views) has also been expanded to have the following module methods: 4 | 5 | * `getCurrentModule()` : Returns the module name of the currently executing module event. 6 | * `getModuleRoot([moduleName])` : Returns the web accessible root to the module's root directory. If you do not pass the explicit module name, we will default to use the `getCurrentModule()` in the request. 7 | 8 | The last method is what is really interesting when building visual modules that need assets from within the module itself. You can easily target the web-accessible path to the module by using the `getModuleRoot()` method. Below are some examples: 9 | 10 | ```javascript 11 | 12 | 13 | 14 | 15 | <---< Base HREF if using SES ---> 16 | 17 | 18 | 19 | 20 | <--- 21 | 22 | 23 | 24 | <---< Module Javascript ---> 25 | 26 | 27 | 28 | 29 | 30 | 31 | The Awesome ForgeBox Module! 32 | 33 | ``` 34 | 35 | As you can see, this is essential when building module UIs or layouts. 36 | -------------------------------------------------------------------------------- /hmvc/modules/url-routing/default-route-execution.md: -------------------------------------------------------------------------------- 1 | # Default Route Execution 2 | 3 | By now, we should all know the default SES route ColdBox offers: `addRoute(":handler/:action?")`. This means that we can target a handler with or without a package and an action for execution. In ColdBox we have also added a package resolver that will detect this pattern for module and package directories so we can do URL safe and SES friendly URLs for these executions by convention. 4 | 5 | If we do not have this feature, this is how the URLs would look like: 6 | 7 | ```javascript 8 | http://mysite.com/module:handler/action 9 | or 10 | http://mysite.com/module:package.handler/action 11 | ``` 12 | 13 | However, thanks to package resolving in the SES interceptor we can do links like this: 14 | 15 | ```javascript 16 | http://mysite.com/module/handler/action 17 | or 18 | http://mysite.com/module/package/handler/action 19 | ``` 20 | 21 | Much better and nicer huh? Of course! So potentially, with one route we could write entire applications. 22 | -------------------------------------------------------------------------------- /hmvc/modules/url-routing/module-routes-files.md: -------------------------------------------------------------------------------- 1 | # Module Routes Files 2 | 3 | A module can also include one or more custom routing files in order to take advantage of our routing DSL and also have better separation as they will be stored outside of the module configuration object. You do this by giving the path to the custom file to include in your routes structure: 4 | 5 | ```javascript 6 | routes = [ 7 | "config/routes" 8 | ]; 9 | ``` 10 | 11 | This will look for a `routes.cfm` template in your module's `config` folder and load it. Please note that you do not need to specify a `.cfm` if you don't want to. You can load as many route files as you like. 12 | 13 | ## ColdBox 5 Router 14 | 15 | If you want to use the ColdBox 5 `Router.cfc` inside your module you can simply place the `Router.cfc` inside the `config` folder and it will load by convention. 16 | -------------------------------------------------------------------------------- /readme/release-history/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: All the major information about ColdBox Releases 3 | --- 4 | 5 | # Release History 6 | 7 | ## Versioning Schema 8 | 9 | ColdBox is maintained under the [Semantic Versioning](http://semver.org) guidelines as much as possible. Releases will be numbered in the following format: 10 | 11 | ``` 12 | .. 13 | ``` 14 | 15 | And constructed with the following guidelines: 16 | 17 | * Breaking backward compatibility bumps the major (and resets the minor and patch) 18 | * New additions without breaking backward compatibility bump the minor (and resets the patch) 19 | * Bug fixes and misc changes bump the patch 20 | 21 | ## LTS - Support Policy 22 | 23 | For all ColdBox releases, updates are provided for 12 months, and security fixes are provided for 2 years after the next major release. 24 | 25 |
VersionReleaseUpdatesSecurity Fixes
6.x202220232025
7.x202320242026
8.x202420252027
9.x202520262028
26 | 27 | ## Releases 28 | 29 | In this section, you will find the release notes and links for each version's documentation. If you are looking for the release notes of previous major versions, use the version switcher at the top left of this documentation book. 30 | 31 | * [Version 7.0 - May 2023](../../) 32 | * [Version 6.0 - August 2020](https://coldbox.ortusbooks.com/v/v6.x/intro/release-history/whats-new-with-6.0.0) 33 | * [Version 5.0 - July 2018](https://coldbox.ortusbooks.com/v/v5.x/intro/introduction/whats-new-with-5.0.0) 34 | * [Version 4.0 - January 2015](https://coldbox.ortusbooks.com/v/v4.x/intro/introduction/whats-new-with-4.0.0) 35 | * Version 3.0 - March 2011 36 | * Version 2.0 - April 2007 37 | * Version 1.0 - June 2006 38 | -------------------------------------------------------------------------------- /readme/release-history/whats-new-with-7.3.0.md: -------------------------------------------------------------------------------- 1 | --- 2 | description: March 2, 2025 3 | --- 4 | 5 | # What's New With 7.3.x 6 | 7 | ## 7.3.1 - March 2, 2025 8 | 9 | ### Bug 10 | 11 | [COLDBOX-1293](https://ortussolutions.atlassian.net/browse/COLDBOX-1293) DBAppender with SQL Server Not Compatible with Adobe 2023 12 | 13 | ## 7.3.0 - May 13, 2024 14 | 15 | ### New Feature 16 | 17 | [COLDBOX-1270](https://ortussolutions.atlassian.net/browse/COLDBOX-1270) Abililty to restart schedulers with a `restart()` method 18 | 19 | ### Improvement 20 | 21 | [COLDBOX-1268](https://ortussolutions.atlassian.net/browse/COLDBOX-1268) WireBox Singleton auto reload now only affects app singletons and not core singletons 22 | 23 | [COLDBOX-1269](https://ortussolutions.atlassian.net/browse/COLDBOX-1269) Do not add double headers if \``event.setHTTPHeader()`\` is called more than once 24 | 25 | [COLDBOX-1273](https://ortussolutions.atlassian.net/browse/COLDBOX-1273) Removal of deprecated CFML functions in core 26 | 27 | [COLDBOX-1275](https://ortussolutions.atlassian.net/browse/COLDBOX-1275) Improved engine detection by the CFMLEngine feature class 28 | 29 | [COLDBOX-1278](https://ortussolutions.atlassian.net/browse/COLDBOX-1278) Remove unsafe `evaluate` function usage 30 | 31 | ### Bug 32 | 33 | [COLDBOX-1266](https://ortussolutions.atlassian.net/browse/COLDBOX-1266) Logger for MS SQL using `date` not `datetime`. 34 | 35 | [COLDBOX-1267](https://ortussolutions.atlassian.net/browse/COLDBOX-1267) Lucee only `isEmpty` function call 36 | 37 | [COLDBOX-1279](https://ortussolutions.atlassian.net/browse/COLDBOX-1279) Render encapsulator bleed of this scope by engines 38 | -------------------------------------------------------------------------------- /readme/what-is-coldbox.md: -------------------------------------------------------------------------------- 1 | # What is ColdBox 2 | 3 | ![](../.gitbook/assets/ColdBoxLogo2015\_300.png) 4 | 5 | ColdBox is a conventions-based MVC framework for ColdFusion (CFML). It is fast, scalable, and runs on CFML engines such as Adobe ColdFusion and the open source CFML engine [Lucee](http://www.lucee.org), for a completely free and open source development stack. ColdBox itself is Professional Open Source Software, backed by [Ortus Solutions](http://www.ortussolutions.com) which provides support, training, architecture, consulting and commercial additions. 6 | 7 | ColdBox was the first ColdFusion (CFML) framework to embrace Conventions Over Configuration and comes with a modular architecture to enhance developer and team productivity. It integrates seamlessly with [CommandBox](http://www.ortussolutions.com/products/commandbox) CLI to provide you with REPL interfaces, package management, console development, testing, and automation. 8 | 9 | Here’s a look at some of the core components of the ColdBox platform. Each of these come bundled with the framework, but are also available as separate stand-alone libraries that can be used in ANY ColdFusion application or framework: 10 | 11 | ## WireBox 12 | 13 | ![](../.gitbook/assets/WireBox.png) 14 | 15 | Managing your domain objects has never been easier with this Dependency Injection and Inversion of Control (IOC) framework. WireBox supports all forms of injection as well as maintaining persistence for your domain objects. WireBox can also interface and provide Java classes, web services, and aspects of the ColdBox framework itself. WireBox also has built-in Aspect Oriented Programming (AOP) support; you’ll never need another Dependency Injection engine again. 16 | 17 | ## LogBox 18 | 19 | ![](../.gitbook/assets/LogBox.png) 20 | 21 | This is a highly-configurable logging library which can be set up to relay messages of different types from any portion of your application to any number of predefined logging appenders. 22 | 23 | ## CacheBox 24 | 25 | ![](../.gitbook/assets/CacheBox.png) 26 | 27 | A highly-versatile caching aggregator and enterprise cache that allows for multiple named caching stores as well as granular control over cache behaviors and eviction policies. CacheBox can interface out of the box with Ehcache, Adobe ColdFusion cache, and any Lucee cache. 28 | -------------------------------------------------------------------------------- /testing/testing-coldbox-applications/coldbox-testing-classes.md: -------------------------------------------------------------------------------- 1 | # ColdBox Testing Classes 2 | 3 | ![ColdBox Testing Classes](../../.gitbook/assets/TestingClasses.png) 4 | 5 | Before we begin our adventures in testing, let's review what classes ColdBox gives you for testing and where you can find them. From the diagram, you can see that our pivot class for testing is the TestBox `BaseSpec` class. 6 | 7 | From that superclass, we have our own ColdBox `BaseTestCase` , our base class for any testing in ColdBox, and the class used for Integration Testing. We then spawn several child classes for targeted testing of different objects in your ColdBox applications: 8 | 9 |
Test ClassDescription
BaseTestCaseUsed for Integration Testing
BaseModelTestUsed for model object unit testing
BaseInterceptorTestUsed for interceptor unit testing
BaseHandlerTestUsed for isolated handler unit testing
10 | 11 | -------------------------------------------------------------------------------- /testing/testing-coldbox-applications/integration-testing/life-cycle-events.md: -------------------------------------------------------------------------------- 1 | # Life-Cycle Events 2 | 3 | ![](<../../../.gitbook/assets/ColdBox Virtual App
Life-Cycle.png>) 4 | 5 | ColdBox testing leverages TestBox's testing life-cycle events ([https://testbox.ortusbooks.com/primers/testbox-bdd-primer/life-cycle-methods](https://testbox.ortusbooks.com/primers/testbox-bdd-primer/life-cycle-methods)) in order to prepare the virtual ColdBox application, request context and then destroy it. By default, a virtual application is loaded for all test cases contained within a test bundle CFC via the `beforeAll()` and destroyed under `afterAll()`. 6 | 7 | ```javascript 8 | function beforeAll(){ 9 | super.beforeAll(); 10 | // do your own stuff here 11 | } 12 | 13 | function afterAll(){ 14 | // do your own stuff here 15 | super.afterAll(); 16 | } 17 | ``` 18 | 19 | > **Important** If you override any of these methods and do not funnel the super call, then you might get cached or unexpected results. 20 | 21 | ## Improving Performance: Unloading ColdBox 22 | 23 | The default for integration testing is that the virtual ColdBox application will be **destroyed** or **unloaded** in **each test**. To keep the virtual application **running across multiple test bundle** tests you will need to use the `unloadColdBox=false` annotation or the `this.unloadColdBox=false` setting in your `beforeAll()` method. This will stop the testing classes from destroying ColdBox and improving performance. 24 | 25 | ```javascript 26 | component extends="coldbox.system.testing.BaseTestCase" unloadColdBox=false{ 27 | 28 | this.unloadColdBox = false; 29 | 30 | function beforeAll(){ 31 | super.beforeAll(); 32 | // do your own stuff here 33 | } 34 | } 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /testing/testing-coldbox-applications/integration-testing/test-setup.md: -------------------------------------------------------------------------------- 1 | # Request Setup() 2 | 3 | Since we are simulating a browser, the testing framework needs to know when to prepare a new virtual request internally. This is achieved via the `setup()` method provided to us via the `BaseTestCase` object. This method internally will simulate a new virtual request, if **NOT**, **every test case will be treated as if you are in the same request.** 4 | 5 | The best way to accomplish this is to leverage the `beforeEach()` life-cycle event method. This makes sure that each spec execution is a new virtual request. 6 | 7 | ```javascript 8 | function run() { 9 | describe( "Main Handler", function() { 10 | 11 | beforeEach( function( currentSpec ) { 12 | // Setup as a new ColdBox request, VERY IMPORTANT. ELSE EVERYTHING LOOKS LIKE THE SAME REQUEST. 13 | setup(); 14 | } ); 15 | 16 | it( "can render the homepage", function() { 17 | var event = this.get( "main.index" ); 18 | expect( event.getValue( name = "welcomemessage", private = true ) ).toBe( "Welcome to ColdBox!" ); 19 | } ); 20 | 21 | it( "can render some restful data", function() { 22 | var event = this.post( "main.data" ); 23 | 24 | debug( event.getHandlerResults() ); 25 | expect( event.getRenderedContent() ).toBeJSON(); 26 | } ); 27 | }); 28 | 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /testing/testing-coldbox-applications/integration-testing/testing-without-virtual-application.md: -------------------------------------------------------------------------------- 1 | # Testing Without Virtual Application 2 | 3 | The `BaseTestCase` leverages an internal virtual ColdBox application so you can do integration testing. Meaning that whenever you extend from the `BaseTestCase` the virtual ColdBox will be loaded. However, you can tell the testing framework to **NOT** load it by using the `this.loadColdBox` variable: 4 | 5 | ```javascript 6 | component extends="coldbox.system.testing.BaseTestCase"{ 7 | // Do not load the Virtual Application 8 | this.loadColdBox = false; 9 | } 10 | ``` 11 | 12 | This is a great approach if you still want to leverage the base test case for unit testing but without loading the entire virtual application. 13 | -------------------------------------------------------------------------------- /testing/testing-coldbox-applications/model-object-testing.md: -------------------------------------------------------------------------------- 1 | # Model Object Testing 2 | 3 | You can test all your model objects directly with no need of doing integration testing. This way you can unit test model objects very very easily using great mocking capabilities. All you need to do is the following: 4 | 5 | ``` 6 | coldbox create model-test path=models.UserService methods=save,list,search --open 7 | ``` 8 | 9 | This testing support class will create your model object, and decorate with mocking capabilities via MockBox and create some mocking classes you might find useful in your model object unit testing. The following are the objects that are placed in the variables scope for you to use: 10 | 11 | * `model` : The target model object to test 12 | * `mockLogger` : A mock logger class 13 | * `mockLogBox` : A mock LogBox class 14 | * `mockCacheBox` : A mock Cache Factory class 15 | * `mockWireBox` : A mock WireBox Injector class 16 | 17 | > **Caution** We do not initialize your model objects for you. This is your job as you might need some mocking first. 18 | 19 | Basic Setup 20 | 21 | ```javascript 22 | /** 23 | * The base model test case will use the 'model' annotation as the instantiation path 24 | * and then create it, prepare it for mocking and then place it in the variables scope as 'model'. It is your 25 | * responsibility to update the model annotation instantiation path and init your model. 26 | */ 27 | component extends="coldbox.system.testing.BaseModelTest" model="UserService"{ 28 | 29 | /*********************************** LIFE CYCLE Methods ***********************************/ 30 | 31 | function beforeAll(){ 32 | // setup the model 33 | super.setup(); 34 | 35 | // init the model object 36 | model.init(); 37 | } 38 | 39 | function afterAll(){ 40 | } 41 | 42 | /*********************************** BDD SUITES ***********************************/ 43 | 44 | function run(){ 45 | 46 | describe( "UserService Suite", function(){ 47 | 48 | it( "should save", function(){ 49 | 50 | }); 51 | 52 | it( "should search", function(){ 53 | 54 | }); 55 | 56 | it( "should list", function(){ 57 | 58 | }); 59 | 60 | 61 | }); 62 | 63 | } 64 | 65 | } 66 | ``` 67 | -------------------------------------------------------------------------------- /testing/testing-coldbox-applications/tips-and-tricks.md: -------------------------------------------------------------------------------- 1 | # Tips & Tricks 2 | 3 | Here are some useful tips for you when doing testing with ColdBox Applications: 4 | 5 | * If you are using relative paths in your application, you might encounter problems since the running application is different from the test application. Try to always use paths based on the application's `AppMapping` 6 | * Always use `relocate()` for relocations so they can be mocked 7 | * Leverage `querySim()` for query mocking 8 | * Leverage [MockBox](https://testbox.ortusbooks.com/mocking/mockbox) for mocking and stubbing 9 | * Integration tests are NOT the same as handler tests. Handler tests will just test the handler CFC in isolation, so it will be your job to mock everything around it. 10 | * You can extend the `coldbox.system.testing.BaseModelTest` to test any domain object 11 | * The [ColdBox source code testing folder](https://github.com/ColdBox/coldbox-platform/tree/master/tests) has over 5,000 tests, mocking scripts and more for you to learn from 12 | -------------------------------------------------------------------------------- /the-basics/event-handlers/how-are-events-called.md: -------------------------------------------------------------------------------- 1 | # How are events called? 2 | 3 | ![](<../../.gitbook/assets/request-lifecycle (1) (1) (1).png>) 4 | 5 | Events are determined via a special variable that can be sent in via the FORM, URL, or REMOTELY called `event`. If no event is detected as an incoming variable, the framework will look in the configuration directives for the `DefaultEvent` and use that instead. If you did not set a `DefaultEvent` setting then the framework will use the following convention for you: `main.index` 6 | 7 | {% hint style="success" %} 8 | **Hint** : You can even change the `event` variable name by updating the `EventName` setting in your `coldbox` [configuration directive](../../getting-started/configuration/coldbox.cfc/configuration-directives/). 9 | {% endhint %} 10 | 11 | Please note that ColdBox supports both normal variable routing and [URL mapping routing](../routing/), usually referred to as pretty URLs. 12 | 13 | ## Event Syntax 14 | 15 | In order to call them you will use the following event syntax notation format: 16 | 17 | ```javascript 18 | event={module:}{package.}{handler}{.action} 19 | ``` 20 | 21 | * **no event** : Default event by convention is `main.index` 22 | * **event={handler}** : Default action method by convention is `index()` 23 | * **event={handler}.{action}** : Explicit handler + action method 24 | * **event={package}.{handler}.{action}** : Packaged notation 25 | * **event={module}:{package}.{handler}.{action}** : Module Notation (See [ColdBox Modules](../../hmvc/modules/)) 26 | 27 | This looks very similar to a Java or CFC method call, example: `String.getLength(),` but without the parentheses. Once the event variable is set and detected by the framework, the framework will tokenize the event string to retrieve the CFC and action call to validate it against the internal registry of registered events. It then continues to instantiate the event handler CFC or retrieve it from cache, finally executing the event handler's action method. 28 | 29 | **Examples** 30 | 31 | ``` 32 | // Call the users.cfc index() method 33 | index.cfm?event=users.index 34 | // Call the users.cfc index() method implicitly 35 | index.cfm?event=users 36 | // Call the users.cfc index() method via URL mappings 37 | index.cfm/users/index 38 | // Call the users.cfc index() method implicitly via URL mappings 39 | index.cfm/users 40 | ``` 41 | -------------------------------------------------------------------------------- /the-basics/event-handlers/interception-methods/README.md: -------------------------------------------------------------------------------- 1 | # Interception Methods 2 | 3 | ![](<../../../.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1) (1) (1) (1).jpg>) 4 | 5 | There are several simple implicit [AOP](http://en.wikipedia.org/wiki/Aspect-oriented\_programming) (Aspect Oriented Programming) interceptor methods, usually referred to as **advices**, that can be declared in your event handler that the framework will use in order to execute them **before/after** and **around** an event as its fired from the current handler. 6 | 7 | This is great for intercepting calls, pre/post processing, localized security, logging, RESTful conventions, and much more. Yes, you got that right, [Aspect Oriented Programming](http://en.wikipedia.org/wiki/Aspect-oriented\_programming) just for you and without all the complicated setup involved! If you declared them, the framework will execute them. 8 | 9 | | **Interceptor Method** | **Description** | 10 | | ---------------------- | ------------------------------------------------------------------ | 11 | | `preHandler()` | Executes **before** any requested action (In the same handler CFC) | 12 | | `pre{action}()` | Executes **before** the `{action}` requested ONLY | 13 | | `postHandler()` | Executes **after** any requested action (In the same handler CFC) | 14 | | `post{action}()` | Executes **after** the `{action}` requested ONLY | 15 | | `aroundHandler()` | Executes **around** any request action (In the same handler CFC) | 16 | | `around{action}()` | Executes **around** the `{action}` requested ONLY | 17 | 18 | ![](../../../.gitbook/assets/eventhandler-around.jpg) 19 | -------------------------------------------------------------------------------- /the-basics/event-handlers/interception-methods/post-advices.md: -------------------------------------------------------------------------------- 1 | # Post Advices 2 | 3 | ![](<../../../.gitbook/assets/eventhandler-prepost (2) (2) (2) (1) (1) (1) (1) (1) (1) (1).jpg>) 4 | 5 | With this interceptor you can intercept local event actions and execute things **after** the requested action executes. You can do it globally by using the `postHandler()` method or targeted to a specific action `post{actionName}()`. 6 | 7 | ```javascript 8 | // executes after any action 9 | function postHandler( event, rc, prc, action, eventArguments ){ 10 | } 11 | 12 | // executes after the list() action ONLY 13 | function postList( event, rc, prc, eventArguments ){ 14 | } 15 | 16 | // concrete examples 17 | function postHandler( event, rc, prc, action, eventArguments ){ 18 | log.info("Finalized executing #action#"); 19 | } 20 | ``` 21 | 22 | The arguments received by these interceptors are: 23 | 24 | * `event` : The request context reference 25 | * `action` : The action name that was intercepted by `postHandler()` 26 | * `eventArguments` : The struct of extra arguments sent to an action if executed via `runEvent()` 27 | * `rc` : The **RC** reference 28 | * `prc` : The **PRC** Reference 29 | 30 | ## Exceptions & Only Lists 31 | 32 | You can fine tune these interception methods by leveraging two public properties in the handler: 33 | 34 | * `this.posthandler_only` : A list of actions that the `postHandler()` action will fire ONLY! 35 | * `this.posthandler_except` : A list of actions that the `postHandler()` action will NOT fire on 36 | 37 | ```javascript 38 | // only fire for the actions: save(), delete() 39 | this.posthandler_only = "save,delete"; 40 | // DO NOT fire for the actions: login(), doLogin(), logout() 41 | this.posthandler_except = "login,doLogin,logout" 42 | ``` 43 | -------------------------------------------------------------------------------- /the-basics/event-handlers/sending-files.md: -------------------------------------------------------------------------------- 1 | # Sending Files 2 | 3 | We all need to deliver files to users at one point in time. ColdBox makes it easy to deliver any type of file even binary files via the [Request Context's](../request-context.md) (event) `sendFile()` method. 4 | 5 | ```javascript 6 | function report( event, rc, prc ){ 7 | var prc.reportFile = reportService.createReport(); 8 | 9 | event 10 | .sendFile( 11 | file = prc.reportFile, 12 | name = "UserReport.xls", 13 | deleteFile = true 14 | ) 15 | .noRender(); 16 | } 17 | ``` 18 | 19 | ### Method Signature 20 | 21 | The API Docs can help you see the entire format of the method: [https://apidocs.ortussolutions.com/coldbox/6.6.1/coldbox/system/web/context/RequestContext.html#sendFile()](https://apidocs.ortussolutions.com/coldbox/6.6.1/coldbox/system/web/context/RequestContext.html#sendFile\(\)) 22 | 23 | The method signature is as follows: 24 | 25 | ```javascript 26 | /** 27 | * This method will send a file to the browser or requested HTTP protocol according to arguments. 28 | * CF11+ Compatibility 29 | * 30 | * @file The absolute path to the file or a binary file to send 31 | * @name The name to send to the browser via content disposition header. If not provided then the name of the file or a UUID for a binary file will be used 32 | * @mimeType A valid mime type to use. If not passed, then we will try to use one according to file type 33 | * @disposition The browser content disposition (attachment/inline) header 34 | * @abortAtEnd If true, then this method will do a hard abort, we do not recommend this, prefer the event.noRender() for a graceful abort. 35 | * @extension Only used for binary files which types are not determined. 36 | * @deleteFile Delete the file after it has been streamed to the user. Only used if file is not binary. 37 | */ 38 | function sendFile( 39 | file="", 40 | name="", 41 | mimeType="", 42 | disposition="attachment", 43 | boolean abortAtEnd="false", 44 | extension="", 45 | boolean deleteFile=false 46 | ) 47 | ``` 48 | 49 | {% hint style="info" %} 50 | Please note that the `file` argument can be an absolute path or an actual binary file to stream out. 51 | {% endhint %} 52 | -------------------------------------------------------------------------------- /the-basics/event-handlers/validation.md: -------------------------------------------------------------------------------- 1 | # Validation 2 | 3 | ColdBox Core MVC does not have validation built-in but it is implemented via the official core `cbValidation` module. You can easily install the module in your application via: 4 | 5 | ```bash 6 | box install cbvalidation 7 | ``` 8 | 9 | You can find much more information about this module in the following resources: 10 | 11 | * **Source**: [https://github.com/coldbox/cbox-validation](https://github.com/coldbox/cbox-validation) 12 | * **Documentation**: [https://coldbox-validation.ortusbooks.com](https://coldbox-validation.ortusbooks.com) 13 | * **ForgeBox** : [http://forgebox.io/view/cbvalidation](http://forgebox.io/view/cbvalidation) 14 | -------------------------------------------------------------------------------- /the-basics/interceptors/core-interception-points/README.md: -------------------------------------------------------------------------------- 1 | # Core Interception Points 2 | 3 | There are many interception points that occur during an MVC and Remote life cycle in a ColdBox application. We highly encourage you to follow our flow diagrams in our [How ColdBox Works](../../../architecture-concepts/how-coldbox-works#request-lifecycle) section so you can see where in the life cycle these events fire. Also remember that each event can pass a data structure that can be used in your application. 4 | -------------------------------------------------------------------------------- /the-basics/interceptors/core-interception-points/cachebox-events.md: -------------------------------------------------------------------------------- 1 | # CacheBox Events 2 | 3 | Our caching engine, [CacheBox](https://cachebox.ortusbooks.com/), also announces several events during its life cycle, so please see The [CacheBox Events Section](https://cachebox.ortusbooks.com/advanced-usage/cachebox-event-model/cachebox-events) as well. 4 | -------------------------------------------------------------------------------- /the-basics/interceptors/core-interception-points/layout-view-events.md: -------------------------------------------------------------------------------- 1 | # Layout-View Events 2 | 3 | | Interception Point | Intercept Structure | Description | 4 | | ------------------ | ----------------------------------------- | ------------------------------------------------------------------------------------------ | 5 | | preLayout | --- | This occurs before any rendering or layout is executed | 6 | | preRender | {renderedContent} | This occurs after the layout+view is rendered and this event receives the produced content | 7 | | postRender | --- | This occurs after the content has been rendered to the buffer output | 8 | | preViewRender | view - The name of the view to render | This occurs before any view is rendered | 9 | | postViewRender | All of the data above plus: | This occurs after any view is rendered and passed the produced content | 10 | | preLayoutRender | layout - The name of the layout to render | This occurs before any layout is rendered | 11 | | postLayoutRender | Everything above plus: | This occurs after any layout is rendered and passed the produced content | 12 | -------------------------------------------------------------------------------- /the-basics/interceptors/core-interception-points/module-events.md: -------------------------------------------------------------------------------- 1 | # Module Events 2 | 3 | | Interception Point | Intercept Structure | Description | 4 | | ------------------ | ------------------------------------------ | ------------------------------------------------------------ | 5 | | preModuleLoad | {moduleLocation, moduleName} | This occurs before any module is loaded in the system | 6 | | postModuleLoad | {moduleLocation, moduleName, moduleConfig} | This occurs after a module has been loaded in the system | 7 | | preModuleUnload | {moduleName} | This occurs before a module is unloaded from the system | 8 | | postModuleUnload | {moduleName} | This occurs after a module has been unloaded from the system | 9 | -------------------------------------------------------------------------------- /the-basics/interceptors/core-interception-points/object-creating-events.md: -------------------------------------------------------------------------------- 1 | # Object Creating Events 2 | 3 | | Interception Point | Intercept Structure | Description | 4 | | --------------------- | ------------------------------ | -------------------------------------------------------------------------------------------- | 5 | | afterHandlerCreation | handlerPath - The handler path | This occurs whenever a handler is created | 6 | | afterInstanceCreation | mapping - The object mapping | This occurs whenever a [wirebox](http://wiki.coldbox.org/wiki/Wirebox.cfm) object is created | 7 | 8 | [WireBox](http://wirebox.ortusbooks.com/content/wirebox\_event\_model/index.html) also announces several other events in the object creation life cycles, so please see [the WireBox events](http://wirebox.ortusbooks.com/content/wirebox\_event\_model/index.html) 9 | -------------------------------------------------------------------------------- /the-basics/interceptors/custom-events/README.md: -------------------------------------------------------------------------------- 1 | # Custom Events 2 | 3 | In addition to all the events announced by the framework, you can also register your own custom events. 4 | 5 | [Curt Gratz](https://vimeo.com/gratzc) shares a brief example and use case for ColdBox custom interception points in his video [ColdBox Custom Interception Points - How To](https://vimeo.com/17409335). 6 | -------------------------------------------------------------------------------- /the-basics/interceptors/custom-events/announcing-interceptions.md: -------------------------------------------------------------------------------- 1 | # Announcing Interceptions 2 | 3 | The last piece of the puzzle is how to announce events. You will do so via the inherited super type method `announce()` that all your handlers,plugins and even the interceptors themselves have or via the interceptor service `announce()` method. This method accepts an incoming data struct which will be broadcasted alongside your event: 4 | 5 | ```javascript 6 | // Announce with no data 7 | announce( "onExit" ); 8 | 9 | // Announce with data 10 | announce( 'onLog', { 11 | time = now(), 12 | user = event.getValue( "user" ), 13 | dataset = prc.dataSet 14 | } ); 15 | 16 | // Announce via interceptor service 17 | controller.getInterceptorService().announce( "onRecordInsert", {} ); 18 | ``` 19 | 20 | > **Hint** Announcing events can also get some asynchronous love, read the [Interceptor Asynchronicity](../interceptor-asynchronicity/) for some asynchronous love. 21 | -------------------------------------------------------------------------------- /the-basics/interceptors/custom-events/configuration-registration.md: -------------------------------------------------------------------------------- 1 | # Configuration Registration 2 | 3 | In the `ColdBox.cfc` configuration file, there is a structure called `interceptorSettings` with two keys: 4 | 5 | * `throwOnInvalidStates` - This tells the interceptor service to throw an exception if the state announced for interception is not valid or does not exist. By default it does not throw an exception but ignore the announcement. 6 | * `customInterceptionPoints` - This key is a comma delimited list of custom interception points you will be registering for execution. 7 | 8 | ```javascript 9 | //Interceptor Settings 10 | interceptorSettings = { 11 | throwOnInvalidStates = false, 12 | customInterceptionPoints = "onLogin,onWikiTranslation,onAppClose" 13 | }; 14 | ``` 15 | 16 | The `customInterceptionPoints` is what interest us. This can be a list or an array of events your system can broadcast. This way, whenever interceptors are registered, they will be inspected for those events. 17 | -------------------------------------------------------------------------------- /the-basics/interceptors/custom-events/listening.md: -------------------------------------------------------------------------------- 1 | # Listening 2 | 3 | Once your custom interception or event points are registered and CFC are registered then you can write the methods for listening to those events just like any other interceptor event: 4 | 5 | ```javascript 6 | component{ 7 | 8 | function onLog(event,data,buffer){ 9 | // your code here 10 | } 11 | 12 | function onRecordInserted(event,data,buffer){ 13 | // your code here 14 | } 15 | 16 | } 17 | ``` 18 | -------------------------------------------------------------------------------- /the-basics/interceptors/custom-events/programmatic-registration.md: -------------------------------------------------------------------------------- 1 | # Programmatic Registration 2 | 3 | You can use the interceptor service to register new events or interception points via the `appendInterceptionPoints()` method. This way you can dynamically register events in your system: 4 | 5 | ```javascript 6 | public any appendInterceptionPoints( array or list customPoints ) 7 | ``` 8 | 9 | The value of the `customPoints` argument can be a list or an array of interception points to register so the interceptor service can manage them for you: 10 | 11 | ```javascript 12 | controller.getInterceptorService() 13 | .appendInterceptionPoints( [ "onLog", "onError", "onRecordInserted" ] ); 14 | ``` 15 | -------------------------------------------------------------------------------- /the-basics/interceptors/dynamic-registration.md: -------------------------------------------------------------------------------- 1 | # Dynamic Registration 2 | 3 | Instead of creating an Interceptor and registering this interceptor programmatically or in configuration, you can do this directly in code by registrering one-off closures with the new `listen` supertype. 4 | 5 | ```javascript 6 | controller.getInterceptorService().listen( function(){ 7 | log.info( "executing from closure listener") 8 | }, "preProcess" ); 9 | ``` 10 | -------------------------------------------------------------------------------- /the-basics/interceptors/how-do-they-work/README.md: -------------------------------------------------------------------------------- 1 | # How do they work? 2 | 3 | Interceptors are CFCs that extend the ColdBox Interceptor class (`coldbox.system.Interceptor`), implement a configuration method called `configure()`, and then contain methods for the events it will listen for. All interceptors are treated as **singletons** in your application, so make sure they are thread safe and var scoped. 4 | 5 | ![](../../../.gitbook/assets/ColdBoxMajorClasses.jpg) 6 | 7 | ``` 8 | /** 9 | * My Interceptor 10 | */ 11 | component extends="coldbox.system.Interceptor"{ 12 | 13 | function configure(){} 14 | 15 | function preProcess( event, interceptData, buffer, rc, prc ){} 16 | } 17 | ``` 18 | 19 | > **Info** You can also remove the inheritance from the CFC (preferred method) and WireBox will extend the `coldbox.system.Interceptor` for you using [Virtual Inheritance](https://wirebox.ortusbooks.com/content/virtual\_inheritance/). 20 | 21 | You can use CommandBox to create interceptors as well: 22 | 23 | ```bash 24 | coldbox create interceptor help 25 | ``` 26 | 27 | ## Registration 28 | 29 | Interceptors can be registered in your `Coldbox.cfc` configuration file using the `interceptors` struct, or they can be registered manually via the system's interceptor service. 30 | 31 | In `ColdBox.cfc`: 32 | 33 | ``` 34 | // Interceptors registration 35 | interceptors = [ 36 | { 37 | class = "cfc.path", //by default this should be interceptors.yourcfcname 38 | name = "unique name/wirebox ID", 39 | properties = { 40 | // configuration 41 | } 42 | } 43 | ]; 44 | ``` 45 | 46 | Registered manually: 47 | 48 | ``` 49 | controller.getInterceptorService().registerInterceptor( interceptorClass="cfc.path" ); 50 | ``` 51 | 52 | ## The `configure()` Method 53 | 54 | The interceptor has one important method that you can use for configuration called `configure()`. This method will be called right after the interceptor gets created and injected with your interceptor properties. 55 | 56 | > **Info** These properties are local to the interceptor only! 57 | 58 | As you can see on the diagram, the interceptor class is part of the ColdBox framework super type family, and thus inheriting the functionality of the framework. 59 | -------------------------------------------------------------------------------- /the-basics/interceptors/interceptor-asynchronicity/async-announcements.md: -------------------------------------------------------------------------------- 1 | # Async Announcements 2 | 3 | The first case involves where you want to completely detach an interception call into the background. You will accomplish this by using the `async=true` argument. This will then detach the execution of the interception into a separate thread and return to you a structure containing information about the thread it created for you. This is a great way to send work jobs, emails, processing and more to the background instead of having the calling thread wait for execution. 4 | 5 | ```javascript 6 | threadData = announce( 7 | state = "onPageCreate", 8 | data = { page= local.page }, 9 | asyncAll = true 10 | ); 11 | ``` 12 | 13 | ## Configuration Arguments 14 | 15 | You can also combine this call with the following arguments: 16 | 17 | * `asyncPriority` : The priority level of the detached thread. By default it uses `normal` priority level. 18 | 19 | ```javascript 20 | threadData = announce( 21 | state = "onPageCreate", 22 | data = { page= local.page }, 23 | asyncAll = true, 24 | asyncPriority = "high" 25 | ); 26 | ``` 27 | -------------------------------------------------------------------------------- /the-basics/interceptors/interceptor-asynchronicity/async-listeners-no-join.md: -------------------------------------------------------------------------------- 1 | # Async Listeners No Join 2 | 3 | The third use case is exactly the same scenario as the async listeners but with the exception that the caller will **not** wait for the spawned threads at all. This is accomplished by using the `asyncAllJoin=false` flag. This tells ColdBox to just spawn, return back a structure of thread information and continue execution of the calling code. 4 | 5 | ```javascript 6 | var threadData = announce( 7 | state = "onPageCreate", 8 | data = {}, 9 | asyncAll = true, 10 | asyncAllJoin = false 11 | ); 12 | ``` 13 | 14 | ## Configuration Arguments 15 | 16 | You can also combine this call with the following arguments: 17 | 18 | * `asyncPriority` : The priority level of each of the spawned threads. By default it uses `normal` priority level 19 | 20 | ```javascript 21 | var threadData = announce( 22 | state = "onPageCreate", 23 | data = {}, 24 | asyncAll = true, 25 | asyncAllJoin = false, 26 | asyncPriority = "high" 27 | ); 28 | ``` 29 | -------------------------------------------------------------------------------- /the-basics/interceptors/interceptor-asynchronicity/async-listeners-with-join.md: -------------------------------------------------------------------------------- 1 | # Async Listeners With Join 2 | 3 | The second use case is where you want to run the interception but multi-thread **all** the interceptor CFCs that are listening to that interception point. So let's say we have our `onPageCreate` announcement and we have 3 interceptors that are listening to that interception point. Then by using the `asyncAll=true` argument, ColdBox will create 3 separate threads, one for each of those interceptors and execute their methods in their appropriate threads. This is a great way to delegate long running processes simultaneously on a specific piece of data. Also, by default, the caller will wait for all of those 3 threads to finalize before continuing execution. So it is a great way to process data and wait until it has become available. 4 | 5 | ```javascript 6 | var threadData = announce( 7 | state = "onPageCreate", 8 | data = {}, 9 | asyncAll = true 10 | ); 11 | ``` 12 | 13 | > **Caution** Please remember that you are also sharing state between interceptors via the `event` and `interceptData`, so make sure you either lock or are careful in asynchronous land. 14 | 15 | ## Configuration Arguments 16 | 17 | You can also combine this call with the following arguments: 18 | 19 | * `asyncPriority` : The priority level of each of the spawned threads. By default it uses `normal` priority level 20 | * `asyncJoinTimeout` : The timeout in milliseconds to wait for all spawned threads. By default it is set to 0, which waits until ALL threads finalize no matter how long they take. 21 | * `asyncAllJoin` : The flag that determines if the caller should wait for all spawned threads or should just spawn all threads and continue immediately. By default, it waits until all spawned threads finalize. 22 | 23 | ```javascript 24 | var threadData = announce(state="onPageCreate", interceptData={}, asyncAll=true, asyncAllJoin=false); 25 | var threadData = announce( 26 | state = "onPageCreate", 27 | data = {}, 28 | asyncAll = true, 29 | asyncAllJoin = false, 30 | asyncJoinTimeout = 30, 31 | asyncPriority = "high" 32 | ); 33 | ``` 34 | -------------------------------------------------------------------------------- /the-basics/interceptors/interceptor-asynchronicity/asynchronous-annotations.md: -------------------------------------------------------------------------------- 1 | # Asynchronous Annotations 2 | 3 | We have also extended the interceptor registration process so you can annotate interception points to denote threading. You will do so with the following two annotations: 4 | 5 | | Argument | Type | Required | Default Value | Description | 6 | | --------------- | -------------------------- | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------- | 7 | | `async` | none | false | false | If the annotation exists, then ColdBox will execute the interception point in a separate thread only if not in a thread already. | 8 | | `asyncPriority` | string : _low,normal,high_ | false | _normal_ | The thread priority that will be sent to each cfthread call that is made by the system. | 9 | 10 | This allows you the flexibility to determine in code which points are threaded, which is a great way to use for emails, logging, etc. 11 | 12 | ```javascript 13 | function preProcess( event, data ) async asyncPriority="low"{ 14 | // Log current request information 15 | log.info("Executing request: #event.getCurrentEvent()#", getHTTPRequestData() ); 16 | } 17 | ``` 18 | 19 | So if you have 3 interceptors in a chain and only 1 of them is threaded, then the 2 will execute in order while the third one in the background. Overall, your processing power and choices have now grown. 20 | -------------------------------------------------------------------------------- /the-basics/interceptors/interceptor-declaration.md: -------------------------------------------------------------------------------- 1 | # Interceptor Declaration 2 | 3 | Interceptors can be declared in the `Coldbox.cfc` configuration file or programmatically at runtime. If you register them in the configuration file, then you have control over the order in which they fire. If you register interceptors programmatically, you won't have control over the order of execution. 4 | 5 | In the configuration file, interceptors are declared as an array of structures in an element called `interceptors`. The elements of each interceptor structure are: 6 | 7 | * `class` - The required instantiation path of the CFC. 8 | * `name` - An optional unique name for the interceptor. If this is not passed then the name of the CFC will be used. We highly encourage the use of a name to avoid collisions. 9 | * `properties` - A structure of configuration properties to be passed to the interceptor 10 | 11 | In `ColdBox.cfc`: 12 | 13 | ``` 14 | // Interceptors registration 15 | interceptors = [ 16 | { 17 | class = "cfc.path", 18 | name = "unique name/wirebox ID", 19 | properties = { 20 | // configuration 21 | } 22 | } 23 | ]; 24 | ``` 25 | 26 | **Example** 27 | 28 | ``` 29 | // Interceptors registration 30 | interceptors = [ 31 | { 32 | class="coldbox.system.interceptors.SES", 33 | properties={} 34 | }, 35 | { 36 | class="interceptors.RequestTrim", 37 | properties={ 38 | trimAll=true 39 | } 40 | }, 41 | { 42 | class="coldbox.system.interceptors.Security", 43 | name="AppSecurity", 44 | properties={ 45 | rulesSource="model", 46 | rulesModel="securityRuleService@cb", 47 | rulesModelMethod="getSecurityRules", 48 | validatorModel="securityService@cb" 49 | } 50 | } 51 | ]; 52 | ``` 53 | 54 | > **Info** Remember that order is important! 55 | -------------------------------------------------------------------------------- /the-basics/interceptors/interceptor-output-buffer.md: -------------------------------------------------------------------------------- 1 | # Interceptor Output Buffer 2 | 3 | Every interception point receives a unique request output buffer that can be used to elegantly produce output. Once the interception point is executed, the interceptor service will check to see if the output buffer has content, if it does it will advice to write the output to the ColdFusion output stream. This way, you can produce output very cleanly from your interception points, without adding any messy-encapsulation breaking `output=true` tags to your interceptors. (**BAD PRACTICE**). This is an elegant solution that can work for both core and custom interception points. 4 | 5 | ```javascript 6 | // Using methods, meaning you inherited from Interceptor or registered at configuration time. 7 | function preRender( event, data, buffer, rc, prc ){ 8 | //clear all of it first, just in case. 9 | arguments.buffer.clear(); 10 | //Append to buffer 11 | arguments.buffer.append( '

This software is copyright by Funky Joe!

' ); 12 | } 13 | ``` 14 | 15 | > **Hint** Each execution point will have its own clean buffer to work with. As each interception point has finalized execution, the output buffer is flushed, only if content exists. 16 | 17 | ## Output Buffer Argument 18 | 19 | Here are some examples using the `buffer` argument: 20 | 21 | ```javascript 22 | function onSidebar( event, data, buffer, rc, prc ){ 23 | savecontent variable="local.data"{ 24 | /// HTML HERE 25 | } 26 | 27 | arguments.buffer.append( local.data ); 28 | } 29 | 30 | // using argument 31 | function preRender( event, data, buffer, rc, prc ){ 32 | //clear all of it first, just in case. 33 | arguments.buffer.clear(); 34 | //Append to buffer 35 | arguments.buffer.append('

This software is copyright by Funky Joe!

'); 36 | } 37 | ``` 38 | 39 | Here are some common methods on the buffer object: 40 | 41 | * `append( str )` Append strings to the buffer 42 | * `clear()` Clear the entire buffer 43 | * `length()` Get size of the buffer 44 | * `getString()` Get the entire string in the buffer 45 | * `getBufferObject()` Get the actual java String Builder object 46 | -------------------------------------------------------------------------------- /the-basics/interceptors/interceptor-registration.md: -------------------------------------------------------------------------------- 1 | # Interceptor Registration 2 | 3 | You can also register CFCs as interceptors programmatically by talking to the application's Interceptor Service that lives inside the main ColdBox controller. You can access this service like so: 4 | 5 | ```javascript 6 | // via the controller 7 | controller.getInterceptorService(); 8 | 9 | // dependency injection 10 | property name="interceptorService" inject="coldbox:interceptorService"; 11 | ``` 12 | 13 | Once you have a handle on the interceptor service you can use the following methods to register interceptors: 14 | 15 | * `registerInterceptor()` - Register an instance or CFC path and discover all events it listens to by conventions 16 | * `registerInterceptionPoint()` - Register an instance in a specific event only 17 | 18 | Here are the method signatures: 19 | 20 | ```javascript 21 | public any registerInterceptor([any interceptorClass], [any interceptorObject], [any interceptorProperties='[runtime expression]'], [any customPoints=''], [any interceptorName]) 22 | 23 | public any registerInterceptionPoint(any interceptorKey, any state, any oInterceptor) 24 | ``` 25 | 26 | **Examples** 27 | 28 | ```javascript 29 | // register yourself to listen to all events declared 30 | controller.getInterceptorService() 31 | .registerInterceptor( interceptorObject=this ); 32 | 33 | // register yourself to listen to all events declared and register new events: onError, onLogin 34 | controller.getInterceptorService() 35 | .registerInterceptor( interceptorObject=this, customPoints="onError,onLogin" ); 36 | 37 | // Register yourself to listen to the onException event ONLY 38 | controller.getInterceptorService() 39 | .registerInterceptionPoint( 40 | interceptorKey="MyService", 41 | state="onException", 42 | oInterceptor=this 43 | ); 44 | ``` 45 | -------------------------------------------------------------------------------- /the-basics/interceptors/reporting-methods.md: -------------------------------------------------------------------------------- 1 | # Reporting Methods 2 | 3 | There are several reporting and utility methods in the interceptor service that I recommend you explore. Below are some sample methods: 4 | 5 | ```javascript 6 | //get the entire state container for preProcess For metadata or reporting 7 | getController().getInterceptorService().getStateContainer('preProcess'); 8 | 9 | //Get all the interception state containers for metadata or reporting 10 | getController().getInterceptorService().getInterceptionStates(); 11 | 12 | //Get all the interception points registered in the application 13 | getController().getInterceptorService().getInterceptionPoints(); 14 | ``` 15 | -------------------------------------------------------------------------------- /the-basics/interceptors/restricting-execution.md: -------------------------------------------------------------------------------- 1 | # Restricting Execution 2 | 3 | You can restrict the execution of an interception point by using the `eventpattern` annotation. This annotation will be placed in the function and the value is a regular expression that the interceptor service uses to match against the incoming event. If the regex matches, the interception function executes, else it skips it. This is a great way for you to create interceptors that only fire not only for the specific interception point you want, but also on the specific incoming event. 4 | 5 | ```javascript 6 | // only execute for the admin package 7 | void function preProcess(event,struct data) eventPattern="^admin\."{} 8 | 9 | // only execute for the blog module 10 | void function preProcess(event,struct data) eventPattern="^blog:"{} 11 | 12 | // only execute for the blog module and the home handler 13 | void function preProcess(event,struct data) eventPattern="^blog:home\."{} 14 | 15 | // only execute for the blog, forums, and shop modules 16 | void function preProcess(event,struct data) eventPattern="^(blog|forum|shop):"{} 17 | 18 | // execute for every event except those with 'authentication' in the name 19 | void function preProcess(event,struct data) eventPattern="^((?!authentication).)*$"{} 20 | ``` 21 | -------------------------------------------------------------------------------- /the-basics/interceptors/unregistering-interceptors.md: -------------------------------------------------------------------------------- 1 | # Unregistering Interceptors 2 | 3 | Each interceptor can unregister itself from any event by using the `unregister( state )` method. This method is found in all Interceptors or can be accessed via the interceptor service as well. 4 | 5 | ```javascript 6 | // Inside an interceptor 7 | unregister( 'preProcess' ); 8 | 9 | // From the interceptor service 10 | controller.getInterceptorService() 11 | .unregister( interceptorName="MyInterceptor", state="preProcess" ); 12 | ``` 13 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/helpers-udfs.md: -------------------------------------------------------------------------------- 1 | # Helpers UDF's 2 | 3 | ColdBox provides you with a way to actually inject your layouts/views with custom UDF's, so they can act as helpers. This is called mixin methods and can be done via the `includeUDF()` method in the supertype or via the following settings: 4 | 5 | * `applicationHelper` - Global helper for layouts, views, and handlers 6 | * `viewsHelper` - Global helper for all layouts and views only 7 | 8 | ```javascript 9 | coldbox.applicationHelper = 'includes/helpers/applicationHelper.cfm'; 10 | coldbox.viewsHelper = "includes/helpers/viewsHelper.cfm"; 11 | ``` 12 | 13 | Additionally, `applicationHelper` can accept a list or array of helper files and will include each of them. 14 | 15 | > **Caution** If you try to inject a method that already exists, the call will fail and the CFML engine will throw an exception. Also, try not to abuse mixins, if you have too many consider refactoring into model objects or plugins. 16 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/implicit-layout-view-declarations.md: -------------------------------------------------------------------------------- 1 | # Implicit Layout-View Declarations 2 | 3 | Now that we have seen what layouts and views are, where they are located and some samples, let's dig deeper. Let's discover the power of implicit layout/view declarations: 4 | 5 | ```javascript 6 | //Register Layouts 7 | layouts = [ 8 | { name = "login", 9 | file = "Layout.tester.cfm", 10 | views = "vwLogin,test", 11 | folders = "tags,pdf/single" 12 | } 13 | ]; 14 | ``` 15 | 16 | This `layouts` setting allows you to implicitly define layout to view/folder assignments without the need of programmatically doing it. This is a time saver and a nice way to pre-define how certain views will be rendered. Let's see more examples: 17 | 18 | ```javascript 19 | //Register Layouts 20 | layouts = [ 21 | { name = "Popup", 22 | file = "Layout.Popup.cfm", 23 | views = "login,test", 24 | folders = "^tags,pdf/single" 25 | }, 26 | { name = "help", 27 | file = "layout.help.cfm", 28 | folders = "^help" 29 | } 30 | ]; 31 | ``` 32 | 33 | In the sample, we declare the layout named `popup` and points to the file `Layout.Popup.cfm`. We can then assign it to views or folders: 34 | 35 | * `Views` : The views to assign to this layout (no cfm extension) 36 | * `Folders` : The folders and its children to assign to this layout. (regex ok) 37 | 38 | This is cool, we can tell the framework that some views and some folders should be rendered within a specific layout. Wow, this opens the possibility of creating nested applications that need different rendering schemas! 39 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/layouts/README.md: -------------------------------------------------------------------------------- 1 | # Layouts 2 | 3 | ![](../../../.gitbook/assets/LayoutViewCombinations.png) 4 | 5 | A layout is simply an HTML file that acts as your shell where views can be rendered in and exists in the `layouts` folder of your application. The layouts can be composed of multiple views and one main view. The main view is the view that gets set in the request collection during a request via `event.setView()` usually in your handlers or interceptors. 6 | 7 | You can have as many layouts as you need in your application and they are super easy to override or assign to different parts of your application. Imagine switching content from a normal HTML layout to a PDF or mobile layout with one line of code. How cool would that be? Well, it's that cool with ColdBox. Another big benefit of layouts, is that you can see the whole picture of the layout, not the usual cfmodule calls where tables are broken, or divs are left open as the module wraps itself around content. The layout is a complete html document and you basically describe where views will be rendered. Much easier to build and simpler to maintain. 8 | 9 | > **Info** Another important aspect of layouts is that they can also consume other layouts as well. So you can create nested layouts very easily via the `renderLayout()` method. 10 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/layouts/basic-layouts.md: -------------------------------------------------------------------------------- 1 | # Basic Layouts 2 | 3 | ```markup 4 | 5 | 6 | 7 | 8 | 9 | #prc.title# 10 | 11 | 12 | 13 | #view( view='tags/header')# 14 | 15 |
16 | 17 | #view()# 18 |
19 | 20 | #view( view='tags/footer' )# 21 | 22 | 23 |
24 | ``` 25 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/layouts/default-layout.md: -------------------------------------------------------------------------------- 1 | # Default Layout 2 | 3 | ## Default Layout 4 | 5 | The default layout in a ColdBox application is `layouts/main.cfm` by convention. You can change this by using the `layoutSettings` in your `Coldbox.cfc`. 6 | 7 | ```javascript 8 | //Layout Settings 9 | layoutSettings = { 10 | defaultLayout = "basic.cfm" 11 | } 12 | ``` 13 | 14 | ## Default View 15 | 16 | There is no default view in ColdBox, but you can configure one by using the same `layoutSettings` configuration directive and the `defaultView` directive: 17 | 18 | ```javascript 19 | //Layout Settings 20 | layoutSettings = { 21 | defaultLayout = "basic.cfm", 22 | defaultView = "noview.cfm" 23 | } 24 | ``` 25 | 26 | This means that if no view is set in the request context, ColdBox will fallback to this view for rendering. 27 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/layouts/layout-events.md: -------------------------------------------------------------------------------- 1 | # Layout Events 2 | 3 | All rendered layouts have associated events that are announced whenever the layout is rendered via ColdBox Interceptors. These are great ways for you to be able to intercept when layouts are rendered and transform them, append to them, or even remove content from them in a completely decoupled approach. The way to listen for events in ColdBox is to write Interceptors, which are essential simple CFC's that by convention have a method that is the same name as the event they would like to listen to. Each event has the capability to receive a structure of information wich you can alter, append or remove from. Once you write these Interceptors you can either register them in your Configuration File or programmatically. 4 | 5 | | Event | Data | Description | 6 | | ------------------ | ----------------------------------------- | -------------------------------------- | 7 | | `preLayoutRender` | layout - The name of the layout to render | Executed before any layout is rendered | 8 | | `postLayoutRender` | All of the data above plus: | Executed after a layout was rendered | 9 | 10 | > **Caution** You can disable the layout events on a per-rendering basis by passing the `prePostExempt` argument as true when calling `renderLayout()` methods. 11 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/layouts/layout-helpers.md: -------------------------------------------------------------------------------- 1 | # Layout Helpers 2 | 3 | Just like views, layouts can also have helpers on a per-layout, per-layout-folder or per-application basis. If the framework detects the helper, it will inject it into the rendering layout so you can use methods, properties or whatever. All you need to do is follow a set of conventions. Let's say we have a layout in the following location: 4 | 5 | ```javascript 6 | /layouts 7 | /general 8 | +main.cfm 9 | ``` 10 | 11 | Then we can create the following templates 12 | 13 | * `mainHelper.cfm` : Helper for the `main.cfm` layout. 14 | * `generalHelper.cfm` : Helper for any layout in the `general` folder. 15 | 16 | ```javascript 17 | /layouts 18 | /general 19 | +main.cfm 20 | +mainHelper.cfm 21 | +generalHelper.cfm 22 | ``` 23 | 24 | That's it. Just append Helper to the layout or folder name and there you go, the framework will use it as a helper for that layout specifically. 25 | 26 | > **Caution** Please note that layout helpers will be inheritenly available to any view rendered inside of the layout. 27 | 28 | ## Application wide helpers 29 | 30 | You can also use the `coldbox.viewsHelper` directive to tell the framework what helper file to use for ALL layouts rendered: 31 | 32 | ``` 33 | coldbox.viewsHelper = "includes/helpers/viewsHelper.cfm; 34 | ``` 35 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/layouts/layouts-from-a-module.md: -------------------------------------------------------------------------------- 1 | # Layouts From A Module 2 | 3 | If you need the set layout to be rendered from a specific module then use the `module` argument from the `setLayout() or renderLayout()` methods: 4 | 5 | ```javascript 6 | component name="general"{ 7 | 8 | function index(event,rc,prc){ 9 | 10 | // call some model for data and put into the request collection 11 | prc.myQuery = getInstance('MyService').getData(); 12 | // set the view for rendering 13 | event.setLayout( name="admin", module="contentbox" ); 14 | 15 | } 16 | 17 | } 18 | ``` 19 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/layouts/nested-layouts.md: -------------------------------------------------------------------------------- 1 | # Nested Layouts 2 | 3 | You can also wrap layouts within other layouts and get incredible reusability. This is accomplished by using the `layout()` method in the Renderer. As always, refer to the CFC API for the latest method arguments and capabilities. 4 | 5 | ```javascript 6 | layout([any layout], [any module=''], [any view=''], [struct args={}], [any viewModule=''], [boolean prePostExempt='false']) 7 | ``` 8 | 9 | So if I wanted to wrap my basic layout in a PDF wrapper layout (`pdf.cfm`) I could do the following: 10 | 11 | ```javascript 12 | 13 | 14 | 15 | 16 | 17 |
18 | #dateformat(now(),"MMM DD, YYYY")# at #timeFormat(now(),"full")# 19 |
20 |
21 |
22 | 23 | 24 | 25 | 26 |
27 | Page #cfdocument.currentpagenumber# of #cfdocument.totalpagecount# 28 |
29 |
30 |
31 | 32 | 33 | 34 | #layout(layout="basic")# 35 | 36 | 37 |
38 | ``` 39 | 40 | That's it! The `layout()` method is extremely powerful as it can allow you to not only nest layouts but actually render a-la-carte layout/view combinations also. 41 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/layouts/overriding-layouts.md: -------------------------------------------------------------------------------- 1 | # Overriding Layouts 2 | 3 | Ok, now that we have started to get funky, let's keep going. How can I change the layout on the fly for a specific view? Very easily, using yet another new method from the event object, called `setLayout()` or the `layout` argument to the `setView()` method. 4 | 5 | ```javascript 6 | event.setLayout( name ); 7 | event.setView( view="", layout=name ); 8 | ``` 9 | 10 | This is great, so we can change the way views are rendered on the fly programmatically. We can switch the content to a PDF in an instant. So let's do that 11 | 12 | ```javascript 13 | function home(event,rc,prc){ 14 | 15 | if( event.valueExists('print') ){ 16 | event.setLayout('layout.PDF'); 17 | } 18 | 19 | // logic here 20 | 21 | // set view 22 | event.setView('general/home'); 23 | 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/views/rendering-external-views.md: -------------------------------------------------------------------------------- 1 | # Rendering External Views 2 | 3 | So what if I want to render a view outside of my application without using the setting explained above? Well, you use the `externalView()` method. 4 | 5 | ```javascript 6 | #externalView(view='/myViewsMapping/tags/footer')# 7 | ``` 8 | 9 | {% hint style="info" %} 10 | If you are using ColdBox 6.4 or older, you will want to use the `renderExternalView()` method name. In ColdBox 6.5.2+, `renderExternalView()` was deprecated in favor of the new `externalView()` method. 11 | {% endhint %} 12 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/views/rendering-with-local-variables.md: -------------------------------------------------------------------------------- 1 | # Rendering With Local Variables 2 | 3 | You can pass localized arguments to the `view() and layout()` methods in order to encapsulate the rendering via the `args` struct argument. Much like how you make method calls with arguments. Inside of your layouts and views you will receive the same `args` struct reference as well. 4 | 5 | This gives you great DRYness (yes that is a word) when building new and edit forms or views as you can pass distinct arguments to distinguish them and keep structure intact. 6 | 7 | ## Universal Form 8 | 9 | ```javascript 10 |

#args.type# User

11 |
12 | ... 13 |
14 | ``` 15 | 16 | ### New Form 17 | 18 | ```javascript 19 | #view(view='forms/universal',args={type='new',action='user.create'})# 20 | ``` 21 | 22 | ### Edit Form 23 | 24 | ```javascript 25 | #view(view='forms/universal',args={type='edit',action='user.update'})# 26 | ``` 27 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/views/view-events.md: -------------------------------------------------------------------------------- 1 | # View Events 2 | 3 | All rendered views have associated events that are announced whenever the view is rendered via ColdBox Interceptors. These are great ways for you to be able to intercept when views are rendered and transform them, append to them, or even remove content from them in a completely decoupled approach. The way to listen for events in ColdBox is to write Interceptors, which are essential simple CFC's that by convention have a method that is the same name as the event they would like to listen to. Each event has the capability to receive a structure of information which you can alter, append or remove from. Once you write these Interceptors you can either register them in your Configuration File or programmatically. 4 | 5 | | Event | Data | Description | 6 | | -------------- | ------------------------------------- | ---------------------------------------------- | 7 | | preViewRender | view - The name of the view to render | Executed before a view is about to be rendered | 8 | | postViewRender | All of the data above plus: | Executed after a view was rendered | 9 | 10 | > **Caution** You can disable the view events on a per-rendering basis by passing the `prePostExempt` argument as true when calling `renderView()` methods. 11 | 12 | ## Sample Interceptor 13 | 14 | Here is a sample interceptor that trims any content before it is renderer: 15 | 16 | ```javascript 17 | component{ 18 | 19 | function postViewRender(event,interceptData){ 20 | interceptData.renderedView = trim( interceptData.renderedView ); 21 | } 22 | } 23 | ``` 24 | 25 | Of course, I am pretty sure you will be more creative than that! 26 | -------------------------------------------------------------------------------- /the-basics/layouts-and-views/views/view-helpers.md: -------------------------------------------------------------------------------- 1 | # View Helpers 2 | 3 | This is a nifty little feature that enables you to create nice helper templates on a per-view, per-folder and per-application basis. If the framework detects the helper, it will inject it into the rendering view so you can use methods, properties or whatever. All you need to do is follow a set of conventions. Let's say we have a view in the following location: 4 | 5 | ```javascript 6 | /views 7 | /general 8 | +home.cfm 9 | ``` 10 | 11 | Then we can create the following templates 12 | 13 | * `homeHelper.cfm` : Helper for the home.cfm view. 14 | * `generalHelper.cfm` : Helper for any view in the general folder. 15 | 16 | ```javascript 17 | /views 18 | /general 19 | +home.cfm 20 | +homeHelper.cfm 21 | +generalHelper.cfm 22 | ``` 23 | 24 | **homeHelper.cfm** 25 | 26 | ```javascript 27 | 28 | // facade to get i18n resource 29 | function $r(){ return getResource(argumentCollection=arguments); } 30 | // cool formatted date function 31 | function today(){ return dateFormat(now(),"full"); } 32 | 33 | ``` 34 | 35 | That's it. Just append Helper to the view or folder name and there you go, the framework will use it as a helper for that view specifically. What can you put in these helper templates: 36 | 37 | * NO BUSINESS CODE 38 | * UI logic functions or properties 39 | * Helper functions or properties 40 | * Dynamic JavaScript or CSS 41 | 42 | > **Hint** External views can also use our helper conventions 43 | 44 | ## Application wide helpers 45 | 46 | You can also use the `coldbox.viewsHelper` directive to tell the framework what helper file to use for ALL views and layouts rendered: 47 | 48 | ``` 49 | coldbox.viewsHelper = "includes/helpers/viewsHelper.cfm; 50 | ``` 51 | -------------------------------------------------------------------------------- /the-basics/models/README.md: -------------------------------------------------------------------------------- 1 | # Models 2 | 3 | ColdBox allows you to integrate with the model layer easily by leveraging **WireBox** as your default dependency injection framework. However, you can integrate your model layer with any third-party DI framework via our `cbioc` module ([https://github.com/ColdBox/cbox-ioc](https://github.com/ColdBox/cbox-ioc)) as well. 4 | 5 | ## Spaghetti Evolution 6 | 7 | Remember this: 8 | 9 | ![](../../.gitbook/assets/spaghetti.png) 10 | 11 | Did you get some spine shivers like I just did? WOW! That is the traditional spaghetti coding style. With ColdBox we are now moving into MVC land and focusing on the model layer. 12 | 13 | ![](<../../.gitbook/assets/MVC (1).png>) 14 | 15 | However, the model layer can even be subdivided into many layers as well as we will investigate in this section. 16 | 17 | ## WireBox 18 | 19 | ![](../../.gitbook/assets/WireBox.png) 20 | 21 | WireBox, our dependency injection and AOP framework, will do all the magic of building, wiring objects with dependencies and helping you persist objects in some state (singletons, transients, request, etc). The main purpose for model integration is to make the developer's development workflow easier! And we all like that Easy button! 22 | 23 | ## Benefits 24 | 25 | * Easily create and retrieve model objects by using one method: `getInstance()` 26 | * Easily handle model or handler dependencies by using `cfproperty` and constructor argument conventions. 27 | * An Injection DSL (Domain Specific Language) has been created to facilitate dependencies 28 | * Easily determine what scope model objects should be persisted in: Transients, Singletons, Cache, Request, Session, etc. 29 | * Easily create a configuration binder to create aliases or complex object relationships (Java, WebServices, RSS, etc.) 30 | * Easily do FORM data binding or advanced ORM data binding 31 | * Easily compose ORM relationships from request data 32 | 33 | Wow! You can do all that? Yes and much more. So let's begin. 34 | -------------------------------------------------------------------------------- /the-basics/models/coding-activeentity-style/README.md: -------------------------------------------------------------------------------- 1 | # Coding: ActiveEntity Style 2 | 3 | Now let's build the same thing but using ColdFusion ORM and our `ActiveEntity` approach from the ColdBox ORM Extensions module. 4 | 5 | ```javascript 6 | + handlers 7 | + contacts.cfc 8 | + models 9 | + Contact.cfc 10 | ``` 11 | -------------------------------------------------------------------------------- /the-basics/models/coding-activeentity-style/contact.cfc.md: -------------------------------------------------------------------------------- 1 | # Contact.cfc 2 | 3 | An object that represents a contact and self-validates using [ColdBox Validation Module](https://github.com/coldbox-modules/cbox-validation/wiki), and is an awesome [ActiveEntity](https://coldbox.ortusbooks.com/the-basics/models/coding-activeentity-style) object. Let's use CommandBox to build it: 4 | 5 | ```bash 6 | coldbox create orm-entity entityName=contact primaryKey=contactID properties=firstName,lastName,email --activeEntity --open 7 | ``` 8 | 9 | Then spice it up with the validation constraints 10 | 11 | ```javascript 12 | /** 13 | * A cool Contact entity 14 | */ 15 | component persistent="true" table="contacts" extends="cborm.models.ActiveEntity"{ 16 | 17 | // Primary Key 18 | property name="contactID" fieldtype="id" column="contactID" generator="native" setter="false"; 19 | 20 | // Properties 21 | property name="firstName" ormtype="string"; 22 | property name="lastName" ormtype="string"; 23 | property name="email" ormtype="string"; 24 | 25 | // validation 26 | this.constraints = { 27 | firstName = {required=true}, 28 | lastName = {required=true}, 29 | email = {required=true, type="email"} 30 | }; 31 | 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /the-basics/models/coding-activeentity-style/contacts-handler.md: -------------------------------------------------------------------------------- 1 | # Contacts Handler 2 | 3 | That's right, go to the handler now, no need of data layers or services, we build them for you! This time, we show you the entire CRUD operations as Active Entity makes life easy! 4 | 5 | ```bash 6 | coldbox create handler name=contacts actions=index,editor,delete,save 7 | ``` 8 | 9 | Then spice it up 10 | 11 | ```javascript 12 | /** 13 | * I am a new handler 14 | */ 15 | component{ 16 | 17 | function index(event,rc,prc){ 18 | prc.contacts = entityNew("Contact").list(sortOrder="lastName",asQuery=false); 19 | event.setView("contacts/index"); 20 | } 21 | 22 | function editor(event,rc,prc){ 23 | event.paramValue("id",0); 24 | prc.contact = entityNew("Contact").get( rc.id ); 25 | event.setView("contacts/editor"); 26 | } 27 | 28 | function delete(event,rc,prc){ 29 | event.paramValue("id",0); 30 | entityNew("Contact").deleteByID( rc.id ); 31 | flash.put( "notice", "Contact Removed!" ); 32 | relocate("contacts"); 33 | } 34 | 35 | function save(event,rc,prc){ 36 | event.paramValue("id",0); 37 | var contact = populateModel( entityNew("Contact").get( rc.id ) ); 38 | if( contact.isValid() ){ 39 | contact.save(); 40 | flash.put( "notice", "Contact Saved!" ); 41 | relocate("contacts"); 42 | } 43 | else{ 44 | flash.put( "errors", contact.getValidationResults().getAllErrors() ); 45 | return editor(event,rc,prc); 46 | } 47 | } 48 | 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /the-basics/models/coding-activeentity-style/orm.md: -------------------------------------------------------------------------------- 1 | # ORM 2 | 3 | You will first make sure your `contacts` datsource exists in the Administrator and then we can declare our ORM settings in our `Application.cfc` 4 | 5 | ```javascript 6 | // ORM Settings 7 | this.ormEnabled = true; 8 | this.datasource = "contacts"; 9 | this.ormSettings = { 10 | cfclocation = "models", 11 | dbcreate = "update", 12 | logSQL = true, 13 | flushAtRequestEnd = false, 14 | autoManageSession = false, 15 | eventHandling = true, 16 | eventHandler = "cborm.models.EventHandler" 17 | }; 18 | ``` 19 | 20 | These are the vanilla settings for using the ORM with ColdBox. Make sure that `flushAtRequestEnd` and `autoManageSession` are set to **false** as the ORM extensions will manage that for you. 21 | 22 | In this example, we also use `dbcreate="update"` as we want ColdFusion ORM to build the database for us which allows us to concentrate on the domain problem at hand and not persistence. You also see that we add our own eventHandler which points to the extension's event handler so we can make Active Entity become well, Active! 23 | 24 | ## Activating ORM injections 25 | 26 | Now open your `ColdBox.cfc` and add the following to activate ORM injections inside of your `configure()` method. 27 | 28 | ```javascript 29 | orm = { injection = { enabled=true } }; 30 | ``` 31 | -------------------------------------------------------------------------------- /the-basics/models/coding-activeentity-style/views.md: -------------------------------------------------------------------------------- 1 | # Views 2 | 3 | Here are the views as well, which are pre-created via CommandBox handler creation command. 4 | 5 | ## index.cfm 6 | 7 | ```javascript 8 | 9 |

Contacts

10 | 11 | 12 |
#flash.get( "notice" )#
13 |
14 | 15 |
#flash.get( "errors" ).toString()#
16 |
17 | 18 | #html.href(href='contacts.editor',text="Create Contact")# 19 |

20 | 21 |
22 | #contact.getLastName()#, #contact.getFirstName()# (#contact.getEmail()#)
23 | #html.href(href='contacts.editor.id.#contact.getContactID()#',text="[ Edit ]")# 24 | #html.href(href='contacts.delete.id.#contact.getContactID()#',text="[ Delete ]",onclick="return confirm('Really Delete?')")# 25 |
26 |
27 |
28 |
29 | ``` 30 | 31 | ## editor.cfm 32 | 33 | Check out our awesome `html` helper object. It can even build the entire forms according to the Active Entity object and bind the values for you! 34 | 35 | ```javascript 36 | 37 |

Contact Editor

38 | 39 | 40 |
#flash.get( "notice" )#
41 |
42 | 43 |
#flash.get( "errors" ).toString()#
44 |
45 | 46 | #html.startForm(action="contacts.save")# 47 | #html.entityFields(entity=prc.contact,fieldwrapper="div")# 48 | #html.submitButton()# or #html.href(href="contacts",text="Cancel")# 49 | #html.endForm()# 50 |
51 | ``` 52 | -------------------------------------------------------------------------------- /the-basics/models/coding-orm-scaffolding/README.md: -------------------------------------------------------------------------------- 1 | # Coding: ORM Scaffolding 2 | 3 | Now let's use the power of ORM and CommandBox to scaffold everything for you :). The help for this command is here: 4 | 5 | ```bash 6 | coldbox create orm-crud help 7 | ``` 8 | 9 | It even creates all the integration tests for you. 10 | -------------------------------------------------------------------------------- /the-basics/models/coding-orm-scaffolding/contacts.cfc.md: -------------------------------------------------------------------------------- 1 | # Contacts.cfc 2 | 3 | Let's use CommandBox to build it: 4 | 5 | ```bash 6 | coldbox create orm-entity entityName=contacts primaryKey=contactID properties=firstName,lastName,email --open 7 | ``` 8 | 9 | Then spice it up with the validation constraints 10 | 11 | ```javascript 12 | /** 13 | * A cool Contact entity 14 | */ 15 | component persistent="true" table="contacts"{ 16 | 17 | // Primary Key 18 | property name="contactID" fieldtype="id" column="contactID" generator="native" setter="false"; 19 | 20 | // Properties 21 | property name="firstName" ormtype="string"; 22 | property name="lastName" ormtype="string"; 23 | property name="email" ormtype="string"; 24 | 25 | // validation 26 | this.constraints = { 27 | firstName = {required=true}, 28 | lastName = {required=true}, 29 | email = {required=true, type="email"} 30 | }; 31 | 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /the-basics/models/coding-orm-scaffolding/orm.md: -------------------------------------------------------------------------------- 1 | # ORM 2 | 3 | You will first make sure your `contacts` datsource exists in the Administrator and then we can declare our ORM settings in our `Application.cfc` 4 | 5 | ```javascript 6 | // ORM Settings 7 | this.ormEnabled = true; 8 | this.datasource = "contacts"; 9 | this.ormSettings = { 10 | cfclocation = "models", 11 | dbcreate = "update", 12 | logSQL = true, 13 | flushAtRequestEnd = false, 14 | autoManageSession = false, 15 | eventHandling = true, 16 | eventHandler = "cborm.models.EventHandler" 17 | }; 18 | ``` 19 | 20 | These are the vanilla settings for using the ORM with ColdBox. Make sure that `flushAtRequestEnd` and `autoManageSession` are set to **false** as the ORM extensions will manage that for you. 21 | 22 | In this example, we also use `dbcreate="update"` as we want ColdFusion ORM to build the database for us which allows us to concentrate on the domain problem at hand and not persistence. You also see that we add our own eventHandler which points to the extension's event handler so we can make Active Entity become well, Active! 23 | 24 | ## Activating ORM injections 25 | 26 | Now open your `ColdBox.cfc` and add the following to activate ORM injections inside of your `configure()` method. 27 | 28 | ```javascript 29 | orm = { injection = { enabled=true } }; 30 | ``` 31 | -------------------------------------------------------------------------------- /the-basics/models/coding-orm-scaffolding/scaffold.md: -------------------------------------------------------------------------------- 1 | # Scaffold 2 | 3 | Now let us relish in the power of the `orm-crud` command: 4 | 5 | ```bash 6 | coldbox create orm-crud entity=models.Contacts pluralName=Contacts 7 | ``` 8 | 9 | That's it. 10 | 11 | ``` 12 | Generated Handler: /Users/lmajano/tmp/restapp/handlers/Contacts.cfc 13 | Generated View: /Users/lmajano/tmp/restapp/views/Contacts/edit.cfm 14 | Generated View: /Users/lmajano/tmp/restapp/views/Contacts/editor.cfm 15 | Generated View: /Users/lmajano/tmp/restapp/views/Contacts/new.cfm 16 | Generated View: /Users/lmajano/tmp/restapp/views/Contacts/index.cfm 17 | ``` 18 | 19 | The command will create the handler with RESTFul capabilities, the views and all the necessary machinery for you to manage Contacts! Now go get a nice latte in celebration! 20 | -------------------------------------------------------------------------------- /the-basics/models/coding-solo-style/README.md: -------------------------------------------------------------------------------- 1 | # Coding: Solo Style 2 | 3 | ![](https://github.com/ortus-docs/coldbox-docs/tree/97b8636ca1e8f4651f1021343c097bb3a7c2e9b9/.gitbook/assets/MVC%2Bobjects.png) 4 | 5 | Now that we have seen all the theory and stuff, let's get down to business and do some examples. We will start with the full coding approach with **no** ORM and then spice it up with ORM, so you can see how awesome ORM can be. The examples will not show the entire application being built, but enough to get you started with the process of modeling everything. Here is a layout of what we will build: 6 | 7 | ```javascript 8 | + handlers 9 | + contacts.cfc 10 | + models 11 | + ContactService.cfc 12 | + ContactDAO.cfc 13 | + Contact.cfc 14 | ``` 15 | 16 | I will create a DAO for this small example, so we can showcase how to talk to multiple objects. You can start a new application with CommandBox if you like: 17 | 18 | ``` 19 | mkdir solo 20 | cd solo 21 | coldbox create app name=solo skeleton=AdvancedScript --installColdBox 22 | server start --rewritesEnable 23 | ``` 24 | -------------------------------------------------------------------------------- /the-basics/models/coding-solo-style/contact.cfc.md: -------------------------------------------------------------------------------- 1 | # Contact.cfc 2 | 3 | An object that represents a contact and self-validates using the `cbvalidation` module. 4 | 5 | ``` 6 | coldbox create model name=Contact --open 7 | ``` 8 | 9 | Then spice up with some properties and constraints: 10 | 11 | ```javascript 12 | component accessors="true"{ 13 | 14 | // properties 15 | property name="firstName"; 16 | property name="lastName"; 17 | property name="email"; 18 | 19 | // validation 20 | this.constraints = { 21 | firstName = {required=true}, 22 | lastName = {required=true}, 23 | email = {required=true, type="email"} 24 | }; 25 | 26 | function init(){ 27 | return this; 28 | } 29 | 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /the-basics/models/coding-solo-style/contactdao.cfc.md: -------------------------------------------------------------------------------- 1 | # ContactDAO.cfc 2 | 3 | Our Contact DAO will talk to the datasource object we declared and do a few queries. Notice that this object is a singleton and has some dependency injection. 4 | 5 | ``` 6 | coldbox create model name=ContactDAO persistence=singleton --open 7 | ``` 8 | 9 | Then spice it up 10 | 11 | ```javascript 12 | component accessors="true" singleton{ 13 | 14 | // Dependency Injection 15 | property name="dsn" inject="coldbox:setting:contacts"; 16 | 17 | function init(){ 18 | return this; 19 | } 20 | 21 | query function getAll(){ 22 | var sql = "SELECT * FROM contacts"; 23 | return queryExecute( sql, {}, { datasource: dsn.name } ); 24 | } 25 | 26 | query function getContact(required contactID){ 27 | var params = { 28 | contactID: { value: arguments.contactID, cfsqltype: "numeric" } 29 | }; 30 | var sql = "SELECT * FROM contacts where contactID = :contactID"; 31 | return queryExecute( sql, params, { datasource: dsn.name } ); 32 | } 33 | 34 | ... ALL OTHER METHODS HERE FOR CRUD .... 35 | 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /the-basics/models/coding-solo-style/contacts-handler.md: -------------------------------------------------------------------------------- 1 | # Contacts Handler 2 | 3 | Let's put all the layers together and make the handler talk to the model. I create different saving approaches, to showcase different integration techniques: 4 | 5 | ``` 6 | coldbox create handler name=Contacts actions=index,newContact,create,save --open 7 | ``` 8 | 9 | Spice it up now 10 | 11 | ```javascript 12 | component{ 13 | 14 | // Dependency Injection 15 | property name="contactService" inject="ContactService"; 16 | 17 | function index(event,rc,prc){ 18 | // Get all contacts 19 | prc.aContacts = contactService.list(); 20 | event.setView("contacts/index"); 21 | } 22 | 23 | function newContact(event,rc,prc){ 24 | event.setView("contacts/newContact"); 25 | } 26 | 27 | function create(event,rc,prc){ 28 | var contact = populateModel( "Contact" ); 29 | // validate it 30 | var vResults = validateModel( contact ); 31 | // Check it 32 | if( vResults.hasErrors() ){ 33 | flash.put( "errors", vResults.getAllErrors() ); 34 | return newContact(event,rc,prc); 35 | } 36 | else{ 37 | flash.put( "notice", "Contact Created!" ); 38 | setNextEvent("contacts"); 39 | } 40 | } 41 | 42 | function save(event,rc,prc){ 43 | event.paramValue("contactID",0); 44 | var contact = populateModel( contactService.get( rc.contactID ) ); 45 | // validate it 46 | var vResults = validateModel( contact ); 47 | // Check it 48 | if( vResults.hasErrors() ){ 49 | flash.put( "errors", vResults.getAllErrors() ); 50 | return newContact(event,rc,prc); 51 | } 52 | else{ 53 | flash.put( "notice", "Contact Saved!" ); 54 | setNextEvent("contacts"); 55 | } 56 | } 57 | } 58 | ``` 59 | 60 | Now that you have finished, go execute the contacts and interact with it. 61 | -------------------------------------------------------------------------------- /the-basics/models/coding-solo-style/contactservice.cfc.md: -------------------------------------------------------------------------------- 1 | # ContactService.cfc 2 | 3 | Here is our service layer and we have added some logging just for fun :). Notice that this object is a singleton and has some dependency injection. 4 | 5 | ``` 6 | coldbox create model name=ContactService persistence=singleton --open 7 | ``` 8 | 9 | Then spice it up 10 | 11 | ```javascript 12 | component accessors="true" singleton{ 13 | 14 | // Dependency Injection 15 | property name="dao" inject="ContactDAO"; 16 | property name="log" inject="logbox:logger:{this}"; 17 | property name="populator" inject="wirebox:populator"; 18 | property name="wirebox" inject="wirebox"; 19 | 20 | function init(){ 21 | return this; 22 | } 23 | 24 | /** 25 | * Get all contacts as an array of objects or query 26 | */ 27 | function list(boolean asQuery=false){ 28 | var q = dao.getAllUsers(); 29 | log.info("Retrieved all contacts", q.recordcount); 30 | 31 | if( asQuery ){ return q; } 32 | 33 | // convert to objects 34 | var contacts = []; 35 | for(var x=1; x lte q.recordcount; x++){ 36 | arrayAppend( contacts, populator.populateFromQuery( wirebox.getInstance("Contact"), q, x ) ); 37 | } 38 | 39 | return contacts; 40 | } 41 | 42 | /** 43 | * Get a persisted contact by ID or new one if 0 or no records 44 | */ 45 | function get(required contactID=0){ 46 | var q = dao.getContact(arguments.contactID); 47 | // if 0 or no records 48 | if( contactID eq 0 OR q.recordcount eq 0 ){ 49 | // return a new object 50 | return wirebox.getInstance("Contact"); 51 | } 52 | // Else return the object 53 | return populator.populateFromQuery( wirebox.getInstance("Contact"), q, 1 ); 54 | } 55 | 56 | ... ALL OTHER METHODS HERE .... 57 | 58 | } 59 | ``` 60 | 61 | Now, some observations of the code: 62 | 63 | * We use the populator object that is included in WireBox to make our lives easier so we can populate objects from queries and deal with objects. 64 | * We also inject a reference to the object factory WireBox so it can create `Contact` objects for us. Why? Well what if those objects had dependencies as well. 65 | -------------------------------------------------------------------------------- /the-basics/models/coding-solo-style/datasource.md: -------------------------------------------------------------------------------- 1 | # Datasource 2 | 3 | Make sure you register a datasource in your ColdFusion administrator, we called ours `contacts` and then register it in your ColdBox configuration so ColdBox can build datasource structs for us. This is totally optional, but we do it to showcase more injections: 4 | 5 | `config/ColdBox.cfc` 6 | 7 | ```javascript 8 | // Settings 9 | settings = { 10 | contacts = { 11 | type = "mysql", 12 | name = "contacts" 13 | } 14 | } 15 | ``` 16 | -------------------------------------------------------------------------------- /the-basics/models/coding-virtual-service-layer/README.md: -------------------------------------------------------------------------------- 1 | # Coding: Virtual Service Layer 2 | 3 | Now let's build the same thing but using ColdFusion ORM and our [Virtual Service Layer](http://wiki.coldbox.org/wiki/ORM:VirtualEntityService.cfm) approach, in which we will use a service layer but virtually built by ColdBox. This will most likely give you 80% of what you would ever need, but in case you need to create your own and customize, then you would build a service object that extends or virtual or base layer. 4 | 5 | ```javascript 6 | + handlers 7 | + contacts.cfc 8 | + models 9 | + Contact.cfc 10 | ``` 11 | -------------------------------------------------------------------------------- /the-basics/models/coding-virtual-service-layer/contacts-handler.md: -------------------------------------------------------------------------------- 1 | # Contacts Handler 2 | 3 | That's right, go to the handler now, no need of data layers or services, we build them for you! 4 | 5 | ```bash 6 | coldbox create handler name=contacts actions=index,editor,delete,save 7 | ``` 8 | 9 | Now spice it up 10 | 11 | ```javascript 12 | /** 13 | * I am a new handler 14 | */ 15 | component{ 16 | 17 | // Inject a virtual service layer binded to the contact entity 18 | property name="contactService" inject="entityService:Contact"; 19 | 20 | function index(event,rc,prc){ 21 | prc.contacts = contactService.list(sortOrder="lastName",asQuery=false); 22 | event.setView("contacts/index"); 23 | } 24 | 25 | function editor(event,rc,prc){ 26 | event.paramValue("id",0); 27 | prc.contact = contactService.get( rc.id ); 28 | event.setView("contacts/editor"); 29 | } 30 | 31 | function delete(event,rc,prc){ 32 | event.paramValue("id",0); 33 | contactService.deleteByID( rc.id ); 34 | flash.put( "notice", "Contact Removed!" ); 35 | setNextEvent("contacts"); 36 | } 37 | 38 | function save(event,rc,prc){ 39 | event.paramValue("id",0); 40 | var contact = populateModel( contactService.get( rc.id ) ); 41 | var vResults = validateModel( contact ); 42 | if( !vResults.hasErrors() ){ 43 | contactService.save( contact ); 44 | flash.put( "notice", "Contact Saved!" ); 45 | setNextEvent("contacts"); 46 | } 47 | else{ 48 | flash.put( "errors", vResults.getAllErrors() ); 49 | return editor(event,rc,prc); 50 | } 51 | } 52 | 53 | } 54 | ``` 55 | -------------------------------------------------------------------------------- /the-basics/models/coding-virtual-service-layer/contacts.cfc.md: -------------------------------------------------------------------------------- 1 | # Contacts.cfc 2 | 3 | Let's use CommandBox to build it: 4 | 5 | ```bash 6 | coldbox create orm-entity entityName=contact primaryKey=contactID properties=firstName,lastName,email --open 7 | ``` 8 | 9 | Then spice it up with the validation constraints 10 | 11 | ```javascript 12 | /** 13 | * A cool Contact entity 14 | */ 15 | component persistent="true" table="contacts"{ 16 | 17 | // Primary Key 18 | property name="contactID" fieldtype="id" column="contactID" generator="native" setter="false"; 19 | 20 | // Properties 21 | property name="firstName" ormtype="string"; 22 | property name="lastName" ormtype="string"; 23 | property name="email" ormtype="string"; 24 | 25 | // validation 26 | this.constraints = { 27 | firstName = {required=true}, 28 | lastName = {required=true}, 29 | email = {required=true, type="email"} 30 | }; 31 | 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /the-basics/models/coding-virtual-service-layer/orm.md: -------------------------------------------------------------------------------- 1 | # ORM 2 | 3 | You will first make sure your `contacts` datsource exists in the Administrator and then we can declare our ORM settings in our `Application.cfc` 4 | 5 | ```javascript 6 | // ORM Settings 7 | this.ormEnabled = true; 8 | this.datasource = "contacts"; 9 | this.ormSettings = { 10 | cfclocation = "models", 11 | dbcreate = "update", 12 | logSQL = true, 13 | flushAtRequestEnd = false, 14 | autoManageSession = false, 15 | eventHandling = true, 16 | eventHandler = "cborm.models.EventHandler" 17 | }; 18 | ``` 19 | 20 | These are the vanilla settings for using the ORM with ColdBox. Make sure that `flushAtRequestEnd` and `autoManageSession` are set to **false** as the ORM extensions will manage that for you. 21 | 22 | In this example, we also use `dbcreate="update"` as we want ColdFusion ORM to build the database for us which allows us to concentrate on the domain problem at hand and not persistence. You also see that we add our own eventHandler which points to the extension's event handler so we can make Active Entity become well, Active! 23 | 24 | ## Activating ORM injections 25 | 26 | Now open your `ColdBox.cfc` and add the following to activate ORM injections inside of your `configure()` method. 27 | 28 | ```javascript 29 | orm = { injection = { enabled=true } }; 30 | ``` 31 | -------------------------------------------------------------------------------- /the-basics/models/coding-virtual-service-layer/views.md: -------------------------------------------------------------------------------- 1 | # Views 2 | 3 | Here are the views as well, isn't it awesome that the views stay the same :), that means we did a good job abstracting our model and controllers. 4 | 5 | ## index.cfm 6 | 7 | ```javascript 8 | 9 |

Contacts

10 | 11 | 12 |
#flash.get( "notice" )#
13 |
14 | 15 |
#flash.get( "errors" ).toString()#
16 |
17 | 18 | #html.href(href='contacts.editor',text="Create Contact")# 19 |

20 | 21 |
22 | #contact.getLastName()#, #contact.getFirstName()# (#contact.getEmail()#)
23 | #html.href(href='contacts.editor.id.#contact.getContactID()#',text="[ Edit ]")# 24 | #html.href(href='contacts.delete.id.#contact.getContactID()#',text="[ Delete ]",onclick="return confirm('Really Delete?')")# 25 |
26 |
27 |
28 |
29 | ``` 30 | 31 | ## editor.cfm 32 | 33 | Check out our awesome `html` helper object. It can even build the entire forms according to the Active Entity object and bind the values for you! 34 | 35 | ```javascript 36 | 37 |

Contact Editor

38 | 39 | 40 |
#flash.get( "notice" )#
41 |
42 | 43 |
#flash.get( "errors" ).toString()#
44 |
45 | 46 | #html.startForm(action="contacts.save")# 47 | #html.entityFields(entity=prc.contact,fieldwrapper="div")# 48 | #html.submitButton()# or #html.href(href="contacts",text="Cancel")# 49 | #html.endForm()# 50 |
51 | ``` 52 | -------------------------------------------------------------------------------- /the-basics/models/conventions-location.md: -------------------------------------------------------------------------------- 1 | # Conventions Location 2 | 3 | All your model objects will be located under your `models` folder of your application root by convention. For a more secure installation, place your models outside of the web root and use a ColdFusion Mapping or WireBox Mapping to access them. 4 | -------------------------------------------------------------------------------- /the-basics/models/domain-modeling/data-layers.md: -------------------------------------------------------------------------------- 1 | # Data Layers 2 | 3 | ![](https://github.com/ortus-docs/coldbox-docs/tree/97b8636ca1e8f4651f1021343c097bb3a7c2e9b9/.gitbook/assets/MVC%2Bobjects.png) 4 | 5 | If I know that my database operations will get very complex or I want to further add separation of concerns, I could add a third class to the mix: `BookGateway.cfc` or `BookDAO.cfc` that could act as my data gateway object. 6 | 7 | Now, there are so many design considerations, architectural requirements and even types of service layer approaches that I cannot go over them and present them. My preference is to create service layers according to my application's functionality (Encompasses 1 or more persistence tables) and create gateways or data layers when needed, especially when not using an ORM. The important aspect here, is that I am thinking about my project's OO design and not how I will persist the data in a database. This, to me, is key! 8 | 9 | Understanding that I am more concerned with my object's behavior than how will I persist their data will make you concentrate your efforts on the business rules, model design and less about how the data will persist. Don't get me wrong, persistence takes part in the design, but it should not drive it. 10 | -------------------------------------------------------------------------------- /the-basics/models/injection-dsl/README.md: -------------------------------------------------------------------------------- 1 | # Injection DSL 2 | 3 | Before we start building our objects, we need to understand how WireBox injects dependencies for us. You can define injections using the configuration inside the binder (like any other DI framework), but the easiest approach is to use our injection annotation and conventions (called the injection DSL). The injection DSL can be applied to `cfproperty`, `cfargument`, `cffunction` or called via `getInstance()` as we saw previously. 4 | 5 | You can utilize the injection DSL by adding an attribute called `inject` to properties, arguments and functions. This attribute is like your code shouting, "**Hey, I need something here. Hello! I need something!**" That something might be another object, setting, cache, etc. The value of the `inject` attribute is a string that represents the concept of retrieving an object mapped in WireBox. It can be an object path, an object ID, a setting, a datasource, custom data, etc. 6 | 7 | > **Info:** If you don't like annotations or find them obtrusive, you don't have to use them :). Just leverage the WireBox binder to define dependencies instead. 8 | 9 | Here are a few examples showing how to apply the injection DSL. 10 | 11 | Property Annotation 12 | 13 | ```javascript 14 | property name="service" inject="MyService"; 15 | ``` 16 | 17 | Constructor Argument Annotation 18 | 19 | ``` 20 | 21 | ``` 22 | 23 | ```javascript 24 | /** 25 | * @myDAO.inject model:MyDAO 26 | */ 27 | function init(myDAO){ 28 | } 29 | ``` 30 | 31 | Setter Method Annotation 32 | 33 | ```javascript 34 | function setMyservice(MyService) inject="MyService"{ 35 | variables.MyService = arguments.MyService; 36 | } 37 | ``` 38 | 39 | You can learn more about the supported injection DSLs in [the WireBox Injection DSL documentation](https://wirebox.ortusbooks.com/usage/injection-dsl). 40 | -------------------------------------------------------------------------------- /the-basics/models/injection-dsl/cachebox-namespace.md: -------------------------------------------------------------------------------- 1 | # CacheBox Namespace 2 | 3 | This DSL namespace is only active if using CacheBox or a ColdBox application context. 4 | 5 | | DSL | Description | 6 | | ----------------------------- | ---------------------------------------------------------------------------------- | 7 | | `cachebox` | Get a reference to the application's CacheBox instance | 8 | | `cachebox:{name}` | Get a reference to a named cache inside of CacheBox | 9 | | `cachebox:{name}:{objectKey}` | Get an object from the named cache inside of CacheBox according to the `objectKey` | 10 | 11 | ```javascript 12 | property name="cacheFactory" inject="cacheBox"; 13 | property name="cache" inject="cachebox:default"; 14 | property name="data" inject="cachebox:default:myKey"; 15 | ``` 16 | -------------------------------------------------------------------------------- /the-basics/models/injection-dsl/entityservice-namespace.md: -------------------------------------------------------------------------------- 1 | # EntityService Namespace 2 | 3 | 4 | 5 | {% hint style="warning" %} 6 | In order to use this namespace you will need the `cborm` module installed in your application: `install cborm` 7 | {% endhint %} 8 | 9 | Gives you the ability to easily inject base ORM services or binded virtual entity services for you: 10 | 11 | | DSL | Description | 12 | | ------------------------ | --------------------------------------------------------------------------------------------------------------- | 13 | | `entityService` | Inject a `BaseORMService` object for usage as a generic service layer | 14 | | `entityService:{entity}` | Inject a `VirtualEntityService` object for usage as a service layer based off the name of the entity passed in. | 15 | 16 | ```javascript 17 | // Generic ORM service layer 18 | property name="genericService" inject="entityService"; 19 | // Virtual service layer based on the User entity 20 | property name="userService" inject="entityService:User"; 21 | ``` 22 | -------------------------------------------------------------------------------- /the-basics/models/injection-dsl/executor-namespace.md: -------------------------------------------------------------------------------- 1 | # Executor Namespace 2 | 3 | The executor namespace is both available in ColdBox and WireBox standalone and it is used to get references to created asynchronous executor thread pools. 4 | 5 | | DSL | Description | 6 | | ----------------- | ----------------------------------------------------- | 7 | | `executor` | Inject an executor using the property name as the key | 8 | | `executor:{name}` | Inject an executor by name | 9 | 10 | 11 | 12 | ```javascript 13 | property name="coldbox-tasks" inject="executor"; 14 | 15 | property name="taskExecutor" inject="executor:myTasks"; 16 | ``` 17 | -------------------------------------------------------------------------------- /the-basics/models/injection-dsl/java-namespace.md: -------------------------------------------------------------------------------- 1 | # Java Namespace 2 | 3 | You can also request Java objects from the injection dsl. 4 | 5 | | DSL | Description | 6 | | -------------- | ---------------------------------------- | 7 | | `java:{class}` | Get a reference to the passed in `class` | 8 | 9 | ```javascript 10 | property name="duration" inject="java:java.time.Duration"; 11 | ``` 12 | -------------------------------------------------------------------------------- /the-basics/models/injection-dsl/logbox-namespace.md: -------------------------------------------------------------------------------- 1 | # LogBox Namespace 2 | 3 | This DSL namespace interacts with the loaded LogBox instance. 4 | 5 | | DSL | Description | 6 | | ------------------------------- | --------------------------------------------------------------------------------------------- | 7 | | `logbox` | Get a reference to the application's LogBox instance | 8 | | `logbox:root` | Get a reference to the root logger | 9 | | `logbox:logger:{category name}` | Get a reference to a named logger by its category name | 10 | | `logbox:logger:{this}` | Get a reference to a named logger using the current target object's path as the category name | 11 | 12 | ```javascript 13 | property name="logbox" inject="logbox"; 14 | property name="log" inject="logbox:root"; 15 | property name="log" inject="logbox:logger:myapi"; 16 | property name="log" inject="logbox:logger:{this}"; 17 | ``` 18 | -------------------------------------------------------------------------------- /the-basics/models/injection-dsl/provider-namespace.md: -------------------------------------------------------------------------------- 1 | # Provider Namespace 2 | 3 | Injects providers of objects, meaning a proxy object that knows how to retrieve and construct the desired target object. This is a great way to delay construction or deal with non-singleton objects without causing memory leaks. 4 | 5 | | DSL | Description | 6 | | ------------------------- | --------------------------------------------------------------------------------------------------------- | 7 | | `provider` | Build an object provider that will return the mapping according to the property, method or argument name. | 8 | | `provider:{name}` | Build an object provider that will return the `{name}` mapping. | 9 | | `provider:{injectionDSL}` | Build an object provider that will return the object that the {`injectionDSL`} refers to | 10 | 11 | ```javascript 12 | // using id 13 | property name="timedService" inject="provider:TimedService"; 14 | 15 | // using DSL 16 | property name="timedService" inject="provider:logbox:logger:{this}"; 17 | ``` 18 | -------------------------------------------------------------------------------- /the-basics/models/object-scopes.md: -------------------------------------------------------------------------------- 1 | # Object Scopes 2 | 3 | You can very easily add persistence to your model+ objects via our annotations or binder configuration. The available scopes are: 4 | 5 | * `transient or no scope` : The default scope. Meaning objects have no scope, they are recreated every single time you request them. 6 | * `singleton` : Objects are created once and live until your Application expires 7 | * `cachebox` : You can store your objects in any CacheBox provider and even provide timeouts for them 8 | * `session` : Store them in the ColdFusion `session` scope 9 | * `server` : Store them in the ColdFusion `server` scope 10 | * `request` : Store them in the ColdFusion `request` scope 11 | * `application` : Store them in the ColdFusion `application` scope 12 | * `CUSTOM` : You can build your own scopes as well. 13 | 14 | ```javascript 15 | // transient 16 | component name="MyService"{} 17 | 18 | // singleton 19 | component name="MyService" singleton{} 20 | 21 | // cache in default provider 22 | component name="MyService" cache="true" cacheTimeout="45" cacheLastAccessTimeout="15"{} 23 | 24 | // cache in another provider 25 | component name="MyService" cachebox="MyProvider" cacheTimeout="45"{} 26 | 27 | // request scope 28 | component name="MyService" scope="request"{} 29 | 30 | // session 31 | component name="MyService" scope="session"{} 32 | ``` 33 | 34 | > **Hint** Pease note that using annotations is optional, you can configure every object in our configuration binder as well. 35 | 36 | * Persistence DSL: [http://wirebox.ortusbooks.com/configuration/mapping-dsl/persistence-dsl](http://wirebox.ortusbooks.com/configuration/mapping-dsl/persistence-dsl) 37 | * Object Persistence & Thread Safety: [http://wirebox.ortusbooks.com/advanced-topics/object-persistence-and-thread-safety](http://wirebox.ortusbooks.com/advanced-topics/object-persistence-and-thread-safety) 38 | -------------------------------------------------------------------------------- /the-basics/routing/html-base-tag.md: -------------------------------------------------------------------------------- 1 | # HTML Base Tag 2 | 3 | The `base` tag in HTML allows you to tell the browser what is the base URL for assets in your application. This is something that is always missed when using frameworks that enable routing. 4 | 5 | {% hint style="info" %} 6 | `base` tag defines the base location for links on a page. Relative links within a document (such as \ 13 | ``` 14 | 15 | {% hint style="danger" %} 16 | **Caution** If you do not use this tag, then every asset reference must be an absolute URL reference. 17 | {% endhint %} 18 | -------------------------------------------------------------------------------- /the-basics/routing/http-method-spoofing.md: -------------------------------------------------------------------------------- 1 | # HTTP Method Spoofing 2 | 3 | Although we have access to all the HTTP verbs, modern browsers still only support **GET** and **POST**. With ColdBox and HTTP Method Spoofing, you can take advantage of **all** the HTTP verbs in your web forms. 4 | 5 | By convention, ColdBox will look for an `_method` field in the **FORM** scope. If one exists, the value of this field is used as the HTTP method instead of the method from the execution. For instance, the following block of code would execute with the **DELETE** action instead of the **POST** action: 6 | 7 | ```markup 8 | 9 |
10 | 11 | 12 |
13 |
14 | ``` 15 | 16 | You can manually add these `_method` fields yourselves, or you can take advantage of ColdBox's HTML Helper `startForm()` method. Just pass the method you like, we will take care of the rest: 17 | 18 | ```markup 19 | 20 | #html.startForm( action = "posts.#prc.post.getId()#", method="DELETE" )# 21 | #html.submitButton( name = "Delete", class = "btn btn-danger" )# 22 | #html.endForm()# 23 | 24 | ``` 25 | -------------------------------------------------------------------------------- /the-basics/routing/requirements/README.md: -------------------------------------------------------------------------------- 1 | # Requirements 2 | 3 | Routing is enabled by **default** in the ColdBox application templates in order to work with URL's like this: 4 | 5 | `http://localhost/index.cfm/home/about` 6 | 7 | As you can see they still contain the `index.cfm` in the URL. In order to enable full URL rewrites that eliminates that `index.cfm` you must have a rewrite enabled webserver like Apache, nginx or IIS or a Java rewrite filter which ships with CommandBox by **default**. 8 | 9 | `http://localhost/home/about` 10 | 11 | CommandBox has built in rewrites powered by Tuckey and you can enable a server with rewrites by running: 12 | 13 | ``` 14 | server start --rewritesEnable 15 | ``` 16 | 17 | {% hint style="danger" %} 18 | **Caution** Some J2EE servlet containers do not support the forwarding of SES parameters via the routing template (`index.cfm`) out of the box. You might need to enable full URL rewriting either through a web server or a J2EE filter. 19 | {% endhint %} 20 | 21 | ## Some Resources 22 | 23 | * [Apache mod\_rewrite](http://httpd.apache.org/docs/current/mod/mod\_rewrite.html) via .htaccess or configuration files (Free) 24 | * [Helicon Tech](http://www.helicontech.com/) ISAPI rewrite filter for IIS (Paid) 25 | * [IIS 7](http://www.iis.net/downloads/microsoft/url-rewrite) native rewrite filter (Free) 26 | * [nginx](http://nginx.org/) native web server (free) 27 | * [Tuckey](http://www.tuckey.org/) J2EE rewrite filter (free) 28 | -------------------------------------------------------------------------------- /the-basics/routing/routing-dsl/routing-groups.md: -------------------------------------------------------------------------------- 1 | # Routing Groups 2 | 3 | There will be a time where your routes will become very verbose and you would like to group them into logical declarations. These groupings can also help you **prefixes** repetitive patterns in many routes with a single declarative construct. These needs are met with the `group()` method in the router. 4 | 5 | ```javascript 6 | function group( struct options={}, body ); 7 | ``` 8 | 9 | The best way to see how it works is by example: 10 | 11 | ```javascript 12 | route( pattern="/news", target="public.news.index" ); 13 | route( pattern="/news/recent", target="public.news.recent" ); 14 | route( pattern="/news/removed", target="public.news.removed" ); 15 | route( pattern="/news/add/:title", target="public.news.add" ); 16 | route( pattern="/news/delete/:slug", target="public.news.remove" ); 17 | route( pattern="/news/v/:slug", target="public.news.view" ); 18 | ``` 19 | 20 | As you can see from the routes above, we have lots of repetitive code that we can clean out. So let's look at the same routes but using some nice grouping action. 21 | 22 | ```javascript 23 | group( { pattern="/news", target="public.news." }, function(){ 24 | route( "/", "index" ) 25 | .route( "/recent", "recent" ) 26 | .route( "/removed", "removed" ) 27 | .route( "/add/:title", "add" ) 28 | .route( "/delete/:slug", "remove" ) 29 | .route( "/v/:slug", "view" ); 30 | } ); 31 | ``` 32 | 33 | The **options** struct can contain any values that you can use within the closure. Grouping can also be very nice when creating [namespaces](routing-namespaces.md), which is our next section. 34 | 35 | -------------------------------------------------------------------------------- /the-basics/routing/routing-dsl/routing-namespaces.md: -------------------------------------------------------------------------------- 1 | # Routing Namespaces 2 | 3 | You can create a-la-carte namespaces for URL routes. **Namespaces** are cool groupings of routes according to a specific URL entry point. So you can say that all URLs that start with `/testing` will be found in the **testing** namespace and it will iterate through the namespace routes until it matches one of them. 4 | 5 | Much how modules work, where you have a module entry point, you can create virtual entry point to **ANY** route by namespacing it. This route can be a module a non-module, package, or whatever you like. You start off by registering the namespace using the `addNamespace( pattern, namespace )` method or the fluent `route().toNamespaceRouting()` method. 6 | 7 | ```javascript 8 | addNamespace( pattern="/testing", namespace="test" ); 9 | route( "/testing" ).toNamespaceRouting( "test" ); 10 | 11 | addNamespace( pattern="/news", namespace="blog" ); 12 | route( "/news" ).toNamespaceRouting( "blog" ); 13 | ``` 14 | 15 | Once you declare the namespace you can use the grouping functionality to declare all the namespace routes or you can use a `route().withNamespace()` combination. 16 | 17 | ```javascript 18 | // Via Grouping 19 | route( "/news" ).toNamespaceRouting( "blog" ) 20 | .group( { namespace = "blog" }, function(){ 21 | route( "/", "blog.index" ) 22 | .route( "/:year-numeric?/:month-numeric?/:day-numeric?", "blog.archives" ); 23 | } ); 24 | 25 | 26 | // Via Routing DSL 27 | addNamespace( "/news", "blog" ); 28 | 29 | route( "/" ) 30 | .withNameSpace( "blog" ) 31 | .to( "blog.index" ); 32 | 33 | route( "/:year-numeric?/:month-numeric?/:day-numeric?" ) 34 | .withNameSpace( "blog" ) 35 | .to( "blog.archives" ); 36 | 37 | ``` 38 | 39 | {% hint style="info" %} 40 | **Hint** You can also register multiple URL patterns that point to the same namespace 41 | {% endhint %} 42 | --------------------------------------------------------------------------------