Skip to content

Latest commit

 

History

History
955 lines (722 loc) · 28.4 KB

File metadata and controls

955 lines (722 loc) · 28.4 KB


ColdBox Snapshots Total Downloads Latest Stable Version Apache2 License

Copyright Since 2005 ColdBox Platform by Luis Majano and Ortus Solutions, Corp
www.coldbox.org | www.ortussolutions.com


📦 ColdBox Flat Application Template

Welcome to the Flat ColdBox application template! 🎉 This is the traditional, straightforward template for building HMVC (Hierarchical Model-View-Controller) web applications using Adobe ColdFusion, Lucee, or BoxLang.

🌟 What is the "Flat" Template?

The Flat template uses the traditional ColdBox structure where all application files reside in the web root. This is the most common and widely-used ColdBox template, perfect for:

  • 🚀 Quick Prototyping - Get started fast without complex directory structures
  • 📚 Learning ColdBox - Straightforward layout makes it easy to understand the framework
  • 🔧 Simple Deployments - Traditional hosting setup with minimal configuration
  • 🌐 Universal Compatibility - Works with Adobe CF, Lucee, and BoxLang

💡 Perfect for: Learning projects, rapid prototyping, internal tools, traditional hosting environments, and teams familiar with standard CFML application structures.

🔒 Need enhanced security? Check out the Modern Template which separates application code from the web root.

⚙️ Requirements

Before getting started, ensure you have the following installed on your operating system:

  1. CommandBox - CLI toolchain, package manager, and server runtime

  2. CFML Engine - Choose your preferred engine:

  3. Java (Optional) - For Maven-based Java dependencies

    • Required only if using Java libraries via Maven
    • Compatible with Java 11+ (Java 21 recommended)

📋 Table of Contents

📁 Directory Structure

The Flat template follows the traditional ColdBox HMVC structure with all files in the web root:

.
├── 📄 Application.cfc              # Application bootstrap & settings
├── 📄 index.cfm                    # Front controller
├── 🎨 favicon.ico                  # Site favicon
├── 🤖 robots.txt                   # SEO robots file
├── 📄 box.json                     # CommandBox package descriptor
├── 📄 server.json                  # CommandBox Server configuration
├── 📄 changelog.md                 # Version changelog
├── 📄 pom.xml                      # Maven Java dependencies
├── 📄 .bxformat.json               # Code formatting rules
├── 📄 .cfconfig.json               # CF engine configuration
├── 📄 .dockerignore                # Docker ignore patterns
├── 📄 .editorconfig                # Editor configuration
├── 📄 .env                         # Environment variables
├── 📄 .env.example                 # Environment variables template
├── 📄 .gitattributes               # Git attributes
├── 📄 .gitignore                   # Git ignore patterns
├── 📄 .markdownlint.json           # Markdown linter rules
│
├── 📂 .github/                     # GitHub community files
│   ├── CONTRIBUTING.md
│   ├── FUNDING.YML
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── ISSUE_TEMPLATE/
│   │   ├── BUG_REPORT.md
│   │   └── FEATURE_REQUEST.md
│   └── workflows/
│       ├── lts.yml
│       ├── pr.yml
│       ├── release.yml
│       ├── snapshot.yml
│       └── tests.yml
│
├── 📂 .vscode/                     # VSCode settings & tasks
│   ├── settings.json
│   └── tasks.json
│
├── 📂 config/                      # Application configuration
│   ├── .htaccess                   # Web server access rules
│   ├── Application.cfc             # Config directory protection
│   ├── Coldbox.cfc                 # Framework settings
│   ├── Router.cfc                  # URL routing definitions
│   ├── WireBox.cfc                 # DI container configuration
│   ├── CacheBox.cfc                # Caching configuration
│   └── Scheduler.cfc               # Scheduled tasks
│
├── 📂 handlers/                    # Event handlers (controllers)
│   └── Main.cfc                    # Default handler
│
├── 📂 models/                      # Business logic layer
│   └── (your models here)
│
├── 📂 views/                       # View templates
│   ├── Application.cfc             # Views directory protection
│   └── main/                       # Views for Main handler
│       ├── index.cfm
│       └── indexHelper.cfm
│
├── 📂 layouts/                     # Layout templates
│   └── Main.cfm                    # Default layout
│
├── 📂 includes/                    # Shared includes & assets
│   ├── helpers/
│   │   └── ApplicationHelper.cfm   # Global helper methods
│   ├── i18n/
│   │   └── i18n_goes_here.txt      # i18n resources placeholder
│   └── images/
│       └── ColdBoxLogo2015_300.png
│
├── 📂 modules_app/                 # Application modules (HMVC)
│   └── (your modules here)
│
├── 📂 tests/                       # Test suites
│   ├── Application.cfc             # Test bootstrap
│   ├── index.bxm                   # BoxLang CLI test runner
│   ├── index.cfm                   # CFML CLI test runner
│   ├── runner.bxm                  # BoxLang HTML test runner
│   ├── runner.cfm                  # CFML HTML test runner
│   ├── test.xml                    # CI test configuration
│   ├── specs/
│   │   ├── integration/            # Integration tests
│   │   │   └── MainSpec.cfc
│   │   └── unit/                   # Unit tests
│   │       └── (your tests here)
│   ├── resources/                  # Test resources
│   │   └── (your test data here)
│   └── assets/                     # Test runner assets (CSS, JS, images)
│
├── 📂 docker/                      # Docker configuration
│   ├── Dockerfile
│   └── docker-compose.yml
│
└── 📂 lib/                         # Framework libraries & Java dependencies
    ├── coldbox/                    # ColdBox framework
    ├── testbox/                    # TestBox testing framework
    └── java/                       # Java JARs (via Maven)

Key Directories

  • handlers/ - Event handlers (controllers) that respond to user requests
  • models/ - Service objects, beans, and business logic
  • views/ - HTML templates rendered by handlers
  • layouts/ - Page layouts that wrap views
  • config/ - Application and framework configuration including caching, scheduling, routing, and DI
  • includes/ - Shared helpers, i18n resources, and static assets
  • tests/ - BDD/TDD test suites using TestBox
  • modules_app/ - Modular HMVC applications within your app
  • docker/ - Docker and Docker Compose configuration

🚀 Quick Start

1. Install Dependencies

First, install all required dependencies including ColdBox and TestBox:

box install

This command reads box.json and installs:

  • ColdBox framework to lib/coldbox/
  • TestBox testing framework to lib/testbox/
  • Development tools (BoxLang for formatting, plus optional coldbox-cli and testbox-cli)

2. Start the Server

Start the embedded CommandBox server:

box server start

The application will be available at: http://localhost:PORT (CommandBox will display the actual port)

3. View Your Application

Open your browser and navigate to the server URL. You should see the ColdBox welcome page!

4. Start Coding

  • Create handlers: coldbox create handler name=YourHandler actions=index,save
  • Create models: coldbox create model name=UserService
  • Create tests: coldbox create integration-test handler=YourHandler

🔧 Application Bootstrap

How It Works

The Flat template uses a simple bootstrap flow:

┌─────────────────────────────────────────────────────────────┐
│ 1. User Request → index.cfm (Front Controller)              │
│ 2. index.cfm calls Application.cfc                          │
│ 3. Application.cfc bootstraps ColdBox framework             │
│ 4. ColdBox loads config/Coldbox.cfc                         │
│ 5. ColdBox loads config/Router.cfc                          │
│ 6. ColdBox executes handler action                          │
│ 7. Handler renders view/layout or returns data              │
└─────────────────────────────────────────────────────────────┘

Key Configuration Files

Application.cfc - Application bootstrap:

component {

    this.name                 = "My ColdBox Application";
    this.sessionManagement    = true;
    this.sessionTimeout       = createTimespan( 0, 1, 0, 0 );
    this.setClientCookies     = true;
    this.setDomainCookies     = true;
    this.scriptProtect        = false;
    this.secureJSON           = false;
    this.timezone             = "UTC";
    this.whiteSpaceManagement = "smart";

    // Java integration for lib/java folder
    this.javaSettings = {
        loadPaths               : [ expandPath( "./lib/java" ) ],
        loadColdFusionClassPath : true,
        reloadOnChange          : false
    };

    // ColdBox Bootstrap Settings
    COLDBOX_APP_ROOT_PATH = getDirectoryFromPath( getCurrentTemplatePath() );
    COLDBOX_APP_MAPPING   = "";
    COLDBOX_CONFIG_FILE   = "";
    COLDBOX_APP_KEY       = "";
    COLDBOX_FAIL_FAST     = true;
    COLDBOX_WEB_MAPPING   = "";

    // Location Mappings
    this.mappings[ "/app" ]     = COLDBOX_APP_ROOT_PATH;
    this.mappings[ "/coldbox" ] = COLDBOX_APP_ROOT_PATH & "lib/coldbox";
}

config/Coldbox.cfc - Framework configuration:

  • Application name and settings
  • Event handlers and implicit events
  • Module locations
  • Caching strategies
  • Logging configuration

config/Router.cfc - URL routing:

  • RESTful API routes
  • Resource routes
  • Conventions-based routing

🛠️ Development Workflows

Code Formatting

Format your code using the BoxLang formatter:

# Format all code
box run-script format

# Check formatting without changes
box run-script format:check

Running Tests

Execute your test suites:

# Run all tests
box testbox run

# Run specific test bundle
box testbox run bundles=tests.specs.integration.MainSpec

# Run with coverage
box testbox run --verbose

Creating Scaffolding

Use ColdBox CLI to generate code:

# Create a handler with actions
coldbox create handler name=Users actions=index,create,save,delete

# Create a model with unit test
coldbox create model name=UserService methods=getAll,save,delete --open

# Create an integration test
coldbox create integration-test handler=Users

# Create a complete REST resource (handler + views + tests)
coldbox create resource name=Products --plural

Server Management

# Start server
box server start

# Stop server
box server stop

# Restart server
box server restart

# Open server in browser
box server open

# View server logs
box server log

🧪 Testing

The Flat template includes a comprehensive testing setup using TestBox, a BDD/TDD testing framework.

Test Structure

tests/
├── Application.cfc          # Test bootstrap
├── index.bxm                # BoxLang CLI test runner
├── index.cfm                # CFML CLI test runner
├── runner.bxm               # BoxLang browser test runner
├── runner.cfm               # CFML browser test runner
├── test.xml                 # CI test configuration
├── specs/
│   ├── integration/         # Integration tests (full request lifecycle)
│   │   └── MainSpec.cfc
│   └── unit/                # Unit tests (individual components)
│       └── (your tests here)
├── resources/               # Test data and fixtures
└── assets/                  # Test runner assets (CSS, JS, images)

Running Tests

# Run all tests
box testbox run

# Run specific test bundle
box testbox run bundles=tests.specs.integration.MainSpec

# Run tests and generate coverage report
box testbox run --verbose

# Run tests in browser
box server start
# Navigate to: http://localhost:PORT/tests/runner.cfm

Writing Integration Tests

Integration tests extend coldbox.system.testing.BaseTestCase:

component extends="coldbox.system.testing.BaseTestCase" {

    function beforeAll() {
        super.beforeAll();
    }

    function run() {
        describe("Main Handler", function() {
            beforeEach(function(currentSpec) {
                // CRITICAL: Call setup() to reset request context
                setup();
            });

            it("can render the homepage", function() {
                var event = this.get("main.index");
                expect(event.getValue(name="welcomeMessage", private=true))
                    .toBe("Welcome to ColdBox!");
            });

            it("can return RESTful data", function() {
                var event = this.post("main.data");
                expect(event.getRenderedContent()).toBeJSON();
            });

            it("can handle relocations", function() {
                var event = execute(event="main.doSomething");
                expect(event.getValue("relocate_event", "")).toBe("main.index");
            });
        });
    }
}

Testing Helpers

The BaseTestCase provides helpful methods:

  • this.get(event) - Execute GET request
  • this.post(event, params) - Execute POST request
  • this.put(event, params) - Execute PUT request
  • this.delete(event) - Execute DELETE request
  • execute(event, private, prePostExempt) - Execute any event
  • getRequestContext() - Get current request context

Best Practices

✅ Always call setup() in beforeEach() to reset the request context ✅ Test one thing per test case ✅ Use descriptive names for your test suites and specs ✅ Test both success and failure paths ✅ Mock external dependencies to isolate your tests

☕ Java Dependencies

If your project relies on Java third-party libraries, you can use the included Maven pom.xml file.

Adding Java Dependencies

  1. Find your dependency at https://central.sonatype.com/
  2. Copy the Maven coordinates (groupId, artifactId, version)
  3. Add to pom.xml:
<dependencies>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.10.1</version>
    </dependency>
</dependencies>
  1. Download the JARs:
mvn install

This downloads all JARs to the lib/java/ folder by default. Configure the output directory in your pom.xml or update this.javaSettings.loadPaths in Application.cfc to point to your desired path.

Managing Java Dependencies

# Install/update dependencies
mvn install

# Remove all downloaded JARs
mvn clean

# Update all dependencies to latest versions
mvn versions:use-latest-versions

Automatic Class Loading

The Application.cfc automatically loads all JARs from the lib/java/ folder:

this.javaSettings = {
    loadPaths               : [ expandPath( "./lib/java" ) ],
    loadColdFusionClassPath : true,
    reloadOnChange          : false
};

🐳 Docker Support

The template includes Docker configuration for containerized deployments.

Building Docker Images

Build a Docker image using the CommandBox base image:

# Build the image
box run-script docker:build

# Run the container
box run-script docker:run

# Access container bash
box run-script docker:bash

Docker Compose Stack

The template includes a docker-compose.yml file with support for multiple databases:

# Start the stack (app + database)
box run-script docker:stack up

# Stop the stack
box run-script docker:stack down

# View logs
box run-script docker:stack logs

Supported Databases:

  • MySQL
  • PostgreSQL
  • Microsoft SQL Server

Edit docker/docker-compose.yml to configure your preferred database.

Dockerfile

The included docker/Dockerfile uses the official CommandBox Docker image:

FROM ortussolutions/commandbox:latest

# Copy app files
COPY . /app

# Install dependencies
RUN box install

# Expose port
EXPOSE 8080

# Start server
CMD ["box", "server", "start"]

🌍 Environment Configuration

The template uses a .env file for environment-specific configuration.

Setup

  1. Copy the example file:
cp .env.example .env
  1. Edit .env with your settings:
# ColdBox Name and Environment
APPNAME=ColdBox
ENVIRONMENT=development

# Database Information
DB_CONNECTIONSTRING=jdbc:mysql://127.0.0.1:3306/coldbox?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useLegacyDatetimeCode=true&allowPublicKeyRetrieval=true
DB_CLASS=com.mysql.jdbc.Driver
DB_BUNDLENAME=com.mysql.cj
DB_BUNDLEVERSION=8.0.30
DB_DRIVER=MySQL
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=coldbox
DB_USER=root
DB_PASSWORD=

# JWT Information
JWT_SECRET=

# S3 Information
S3_ACCESS_KEY=
S3_SECRET_KEY=
S3_REGION=us-east-1
S3_DOMAIN=amazonaws.com
  1. Access in your code using getSystemSetting():
// In config/Coldbox.cfc
variables.coldbox = {
    appName: getSystemSetting("APPNAME", "Default App Name")
};

// In your handlers/models
var dbHost = getSystemSetting("DB_HOST", "localhost");
var dbPassword = getSystemSetting("DB_PASSWORD");

Environment Detection

The template automatically detects the environment:

  • Development - Local development machine
  • Staging - Pre-production environment
  • Production - Live environment

Configure environment-specific settings in config/Coldbox.cfc:

function development() {
    variables.coldbox.handlersIndexAutoReload = true;
}

function production() {
    variables.coldbox.handlersIndexAutoReload = false;
    variables.coldbox.handlerCaching = true;
}

💉 Dependency Injection

The Flat template leverages WireBox, ColdBox's dependency injection framework.

Basic Injection

Use the @inject annotation to inject dependencies:

// In a handler
component extends="coldbox.system.EventHandler" {

    property name="userService" inject="UserService";

    function index(event, rc, prc) {
        prc.users = userService.getAll();
        event.setView("users/index");
    }
}

Model Example

// models/UserService.cfc
component singleton {

    property name="log" inject="logbox:logger:{this}";

    function getAll() {
        log.info("Fetching all users");
        return queryExecute("SELECT * FROM users");
    }

    function save(required struct data) {
        // Save user logic
    }
}

Injection DSL

WireBox provides a powerful injection DSL:

  • @inject="model" - Inject by model name
  • @inject="id:MyService" - Inject by specific ID
  • @inject="provider:UserService" - Inject a provider (lazy loading)
  • @inject="logbox:logger:{this} - Inject a logger for this component
  • @inject="cachebox:default" - Inject the default cache
  • @inject="wirebox" - Inject the WireBox injector itself

Configuration

Configure WireBox in config/WireBox.cfc (optional):

component extends="coldbox.system.ioc.config.Binder" {

    function configure() {
        // Map custom objects
        map("SecurityService").to("models.security.SecurityService");

        // Map interfaces to implementations
        map("IUserService").to("models.UserService");
    }
}

🎯 Handler Patterns

Handlers (controllers) respond to user requests and coordinate application flow.

Basic Handler

component extends="coldbox.system.EventHandler" {

    /**
     * Default action
     */
    function index(event, rc, prc) {
        prc.welcomeMessage = "Hello World!";
        event.setView("main/index");
    }

    /**
     * RESTful JSON response
     */
    function data(event, rc, prc) {
        return [
            {id: 1, name: "Alice"},
            {id: 2, name: "Bob"}
        ];
    }

    /**
     * Relocation example
     */
    function save(event, rc, prc) {
        // Save logic here
        relocate("main.index");
    }
}

Handler Arguments

Every handler action receives three arguments:

  • event - Request context with methods to get/set values, render views, etc.
  • rc - Request collection (URL and FORM scopes combined)
  • prc - Private request collection (not accessible from URL)

Common Event Methods

// Get request values
var id = event.getValue("id", 0);
var name = event.getPrivateValue("name");

// Set values
event.setValue("result", data);
event.setPrivateValue("user", userObj);

// Rendering
event.setView("users/edit");
event.setLayout("admin");
return event.renderData(data=result, type="json");

// Relocations
event.overrideEvent("users.list");
relocate("users.index");

Lifecycle Methods

Handlers support implicit lifecycle events:

function onAppInit(event, rc, prc) {
    // Called once when application starts
}

function onRequestStart(event, rc, prc) {
    // Called before each request
}

function onRequestEnd(event, rc, prc) {
    // Called after each request
}

function onException(event, rc, prc) {
    // Called when an exception occurs
    var exception = prc.exception;
    log.error("Error occurred", exception);
}

🛣️ Routing

The template uses config/Router.cfc to define URL routes.

Basic Routes

component {
    function configure() {
        // Simple route
        route("/about").to("main.about");

        // Route with parameters
        route("/users/:id").to("users.show");

        // Route with closure
        route("/api/health", function(event, rc, prc) {
            return {status: "OK", timestamp: now()};
        });

        // Conventions-based routing (catch-all)
        route(":handler/:action?").end();
    }
}

RESTful Resources

resources("photos"); // Creates 7 RESTful routes

// Equivalent to:
// GET    /photos          -> photos.index
// GET    /photos/new      -> photos.new
// POST   /photos          -> photos.create
// GET    /photos/:id      -> photos.show
// GET    /photos/:id/edit -> photos.edit
// PUT    /photos/:id      -> photos.update
// DELETE /photos/:id      -> photos.delete

Route Groups

group({prefix: "/api/v1"}, function() {
    route("/users").to("api.users.index");
    route("/products").to("api.products.index");
});

🔧 VSCode Helpers

The template includes VSCode configuration for enhanced development experience.

Included Files

  • .vscode/settings.json - IntelliSense for ColdBox and TestBox
  • .vscode/tasks.json - Quick tasks for common operations

Custom Tasks

Run CommandBox Task - Execute CommandBox tasks quickly Run TestBox Bundle - Run tests from current file

Usage:

  1. Open Command Palette (Cmd+Shift+P or Ctrl+Shift+P)
  2. Select Tasks: Run Build Task
  3. Or use shortcut: ⇧⌘B (Mac) / Shift+Ctrl+B (Windows)

Recommended Extensions

Install these VSCode extensions for the best development experience:

  • CFML by KamasamaK - Language support and IntelliSense
  • CFLint - CFML linting
  • vscode-coldbox - ColdBox snippets and commands

🎁 ColdBox Features

ColdBox is a professional, conventions-based HMVC framework packed with features:

📚 Learning Resources

Official Documentation

Video Learning

CFCasts - Premium video training platform https://www.cfcasts.com

Get access to hundreds of ColdBox tutorials, from beginner to advanced topics.

Community

💰 Sponsors

ColdBox is a professional open-source project completely funded by the community and Ortus Solutions, Corp.

Become a Sponsor

Support ColdBox development and get awesome benefits:

  • 🎥 CFCasts Account - Access to premium video training
  • 📦 ForgeBox Pro - Advanced package management features
  • 🎫 Event Discounts - Discounts on Into the Box conference
  • 🏆 Recognition - Your logo on our website and documentation

Visit our Patreon page: https://patreon.com/ortussolutions

🔗 Important Links

📄 License

Apache License, Version 2.0.

See LICENSE for details.

🙏 THE DAILY BREAD

"I am the way, and the truth, and the life; no one comes to the Father, but by me (JESUS)" — John 14:6