As a template author, I want templates to use Apache Velocity syntax so that I can leverage familiar QQQ patterns and take advantage of Velocity's powerful features (macros, control flow, method calls).
Design
Current State
The template engine uses jknack/handlebars.java with custom helpers:
{{lowercase x}}, {{uppercase x}}
{{camelCase x}}, {{pascalCase x}}
{{kebabCase x}}, {{snakeCase x}}
Path rendering uses simple {{var}} replacement.
Target State
Replace with Apache Velocity:
Content: $variable, ${variable.method()}
Helpers become Velocity tools in context
Control flow: #if...#else...#end, #foreach
Macros for reusable template fragments
Velocity Tool Equivalents
Handlebars
Velocity
{{lowercase x}}
$str.lower($x)
{{uppercase x}}
$str.upper($x)
{{camelCase x}}
$str.camel($x)
{{pascalCase x}}
$str.pascal($x)
{{kebabCase x}}
$str.kebab($x)
{{snakeCase x}}
$str.snake($x)
Path Rendering
Paths will also use Velocity: src/main/java/$packagePath/ instead of src/main/java/{{packagePath}}/
Successfully replaced Handlebars with Apache Velocity template engine. All 51 tests pass, including 15 new tests for template rendering and 36 existing tests.
This work was completed as part of the broader Epic #12 implementation.
## Implementation Complete
The Velocity template engine has been fully implemented and is working in production. Key deliverables:
- Replaced Handlebars with Apache Velocity 2.3
- Created `StringTool` class with `lower()`, `upper()`, `camel()`, `pascal()`, `kebab()`, `snake()` methods
- Updated `TemplateEngine` to use `VelocityEngine` and `VelocityContext`
- Path rendering uses Velocity variables (`$packagePath`)
- Native image builds successfully with Velocity
- All tests updated and passing
This work was completed as part of the broader Epic #12 implementation.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of #12
User Story
As a template author, I want templates to use Apache Velocity syntax so that I can leverage familiar QQQ patterns and take advantage of Velocity's powerful features (macros, control flow, method calls).
Design
Current State
The template engine uses jknack/handlebars.java with custom helpers:
{{lowercase x}},{{uppercase x}}{{camelCase x}},{{pascalCase x}}{{kebabCase x}},{{snakeCase x}}Path rendering uses simple
{{var}}replacement.Target State
Replace with Apache Velocity:
$variable,${variable.method()}#if...#else...#end,#foreachVelocity Tool Equivalents
{{lowercase x}}$str.lower($x){{uppercase x}}$str.upper($x){{camelCase x}}$str.camel($x){{pascalCase x}}$str.pascal($x){{kebabCase x}}$str.kebab($x){{snakeCase x}}$str.snake($x)Path Rendering
Paths will also use Velocity:
src/main/java/$packagePath/instead ofsrc/main/java/{{packagePath}}/Files to Create/Modify
qctl-qqq/pom.xmlTemplateEngine.javaStringTool.javaTemplateEngineTest.javaImplementation Tasks
org.apache.velocity:velocity-engine-core:2.3dependencycom.github.jknack:handlebars:4.xdependencyStringToolclass withlower(),upper(),camel(),pascal(),kebab(),snake()methodsTemplateEngineconstructor to initializeVelocityEnginerenderContent()to useVelocityContextandStringWriterrenderPath()to use Velocity for path variable substitution$strtool to context automaticallyAcceptance Criteria
$variablesyntax$str.camel(), etc.)#if,#foreach)Implementation Approach - Story #18
Design Decisions
Path Syntax: Velocity syntax everywhere
$variablesyntax (e.g.,src/main/java/$packagePath/App.java)$variableand${variable}formsError Handling: Fail fast with exceptions
TemplateRenderExceptionTemplateRenderExceptionTool Naming:
$strprefix for StringTool$str.camel($value)- camelCase$str.pascal($value)- PascalCase$str.kebab($value)- kebab-case$str.snake($value)- snake_case$str.lower($value)- lowercase$str.upper($value)- UPPERCASETesting: TDD with full coverage
Implementation Order
StringTool.javawith transformation methodspom.xml- swap Handlebars for VelocityTemplateEngine.javato use VelocityEnginereflect-config.jsonfor native imageFiles to Modify
qctl-qqq/pom.xmlqctl-qqq/src/main/java/.../template/TemplateEngine.javaqctl-qqq/src/main/java/.../template/StringTool.javaqctl-qqq/src/main/java/.../template/TemplateRenderException.javaqctl-qqq/src/test/java/.../template/TemplateEngineTest.javaqctl-qqq/src/test/java/.../template/StringToolTest.javaqctl-qqq/src/main/resources/META-INF/native-image/reflect-config.jsonBreaking Changes
{{var}}to$var{{pascalCase var}}to$str.pascal($var)templates-hubwill need migration (Story #22)Implementation Complete
Summary
Successfully replaced Handlebars with Apache Velocity template engine. All 51 tests pass, including 15 new tests for template rendering and 36 existing tests.
Changes Made
pom.xmlvelocity.versionproperty (2.4.1), removedhandlebars.versionqctl-qqq/pom.xmlTemplateEngine.javaStringTool.javalower(),upper(),camel(),pascal(),kebab(),snake()TemplateRenderException.javaStringToolTest.javaTemplateEngineTest.javareflect-config.jsonInitCommand.javaVerification
Acceptance Criteria Status
$variablesyntax$str.camel(), etc.)#if,#foreach)Next Steps
Implementation Complete
The Velocity template engine has been fully implemented and is working in production. Key deliverables:
StringToolclass withlower(),upper(),camel(),pascal(),kebab(),snake()methodsTemplateEngineto useVelocityEngineandVelocityContext$packagePath)This work was completed as part of the broader Epic #12 implementation.