Skip to content

CAMEL-21208: Replace manual string-based code generation with FreeMarker templates#22200

Open
gnodet wants to merge 5 commits intomainfrom
CAMEL-21208-freemarker-templates
Open

CAMEL-21208: Replace manual string-based code generation with FreeMarker templates#22200
gnodet wants to merge 5 commits intomainfrom
CAMEL-21208-freemarker-templates

Conversation

@gnodet
Copy link
Copy Markdown
Contributor

@gnodet gnodet commented Mar 23, 2026

JIRA: CAMEL-21208

Summary

  • Add FreeMarker 2.3.34 as a template engine dependency to camel-jbang-core
  • Replace 23 .tmpl files with .ftl FreeMarker templates using square-bracket syntax ([=var], [#if], [#list]) to avoid conflicts with Maven ${...} and XML <...> syntax
  • Create TemplateHelper utility class that configures FreeMarker with SQUARE_BRACKET_INTERPOLATION_SYNTAX and SQUARE_BRACKET_TAG_SYNTAX, and strips <#-- --> license headers from output
  • Refactor ExportCamelMain, ExportSpringBoot, ExportQuarkus, Export, Run, and KubernetesExport to build model maps and call TemplateHelper.processTemplate() instead of manual regex/string replacements
  • Extract shared helpers into ExportBaseCommand: buildRepositoryList(), buildDependencyList(), formatBuildProperties()
  • Remove 4 unreferenced template fragments (main-docker-*.tmpl, main-jkube-pom.tmpl), consolidating their logic into main-pom.ftl
  • Maintain backward compatibility in ExportSpringBoot for catalog-provided .tmpl templates (falls back to legacy regex processing)
  • Maintain backward compatibility in Init.java for both old {{ .Name }} and new [=Name] placeholder syntax
  • Keep bind templates (.tmpl with TemplateProvider interface) unchanged — separate subsystem
  • Comprehensive unit tests for all 23 templates: FreeMarker-processed and Init (raw text) templates, covering license header stripping, placeholder resolution, conditional rendering, list iteration, Maven ${...} passthrough, Kamelet {{...}} passthrough, and error handling

Test plan

  • Unit tests for all FreeMarker-processed templates via TemplateHelper.processTemplate()
  • Unit tests for all Init templates via raw text loading + header stripping + placeholder replacement
  • Verify Maven ${...} expressions pass through untouched in POM templates
  • Verify Kamelet {{...}} expressions pass through untouched in kamelet templates
  • Verify missing template throws IOException
  • CI green on JDK 17, 21, 25

@github-actions
Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using build-all, build-dependents, skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@github-actions github-actions bot added the dsl label Mar 23, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 23, 2026

🧪 CI tested the following changed modules:

  • dsl/camel-jbang/camel-jbang-core
  • dsl/camel-jbang/camel-jbang-plugin-kubernetes

⚠️ Some tests are disabled on GitHub Actions (@DisabledIfSystemProperty(named = "ci.env.name")) and require manual verification:

  • dsl/camel-jbang/camel-jbang-core: 1 test(s) disabled on GitHub Actions
  • dsl/camel-jbang/camel-jbang-plugin-kubernetes: 8 test(s) disabled on GitHub Actions

💡 Manual integration tests recommended:

You modified dsl/camel-jbang/camel-jbang-core, dsl/camel-jbang/camel-jbang-plugin-kubernetes. The related integration tests in dsl/camel-jbang/camel-jbang-it are excluded from CI. Consider running them manually:

mvn verify -f dsl/camel-jbang/camel-jbang-it -Djbang-it-test

⚙️ View full build and test results

String ftlName = "Dockerfile" + javaVersion + ".ftl";
String context;
try {
Map<String, Object> model = new HashMap<>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be extracted to avoid code duplication?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code on behalf of Guillaume Nodet

Good catch. Looking at this more carefully — the Dockerfile template rendering now uses FreeMarker through the base class, and the Quarkus override handles the fast-jar vs uber-jar distinction which genuinely needs different logic. So the apparent duplication in Export.java line 311 is the shared base implementation. Will add a clarifying comment.

@apupier
Copy link
Copy Markdown
Contributor

apupier commented Mar 25, 2026

Hey AI agent, please rebase and resolve the conflict

@gnodet gnodet force-pushed the CAMEL-21208-freemarker-templates branch from a02cd76 to 2870d10 Compare March 27, 2026 08:09
Copy link
Copy Markdown
Contributor

@orpiske orpiske left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking at this ... it's great to see this cleanup on the code base.

* @param model the data model
* @return the processed template output
*/
public static String processTemplate(String templateName, Map<String, Object> model) throws IOException {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe cover this one with a brief test to ensure future work doesn't break it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added TemplateHelperTest with 6 tests covering: simple interpolation, license header stripping, conditional rendering ([#if]), list rendering ([#list]), Maven expression pass-through (${...}), and missing template error handling.

Claude Code on behalf of Guillaume Nodet

@apupier
Copy link
Copy Markdown
Contributor

apupier commented Apr 2, 2026

What's the status? Is it ready for another review round? If yes, you should re-request a review from Croway so that he can be aware of it

@orpiske orpiske requested a review from Croway April 2, 2026 08:41
@gnodet
Copy link
Copy Markdown
Contributor Author

gnodet commented Apr 3, 2026

What's the status? Is it ready for another review round? If yes, you should re-request a review from Croway so that he can be aware of it

Yes it is.
@Croway

@github-actions github-actions bot added the docs label Apr 3, 2026
@Croway
Copy link
Copy Markdown
Contributor

Croway commented Apr 3, 2026

@gnodet I just did a rerun of all the jobs, by any chance did you run dsl/camel-jbang/camel-jbang-it tests? otherwise we can go YOLO and test on the Jenkins CI directly

@gnodet
Copy link
Copy Markdown
Contributor Author

gnodet commented Apr 9, 2026

Claude Code on behalf of Guillaume Nodet

@Croway Yes, I ran the dsl/camel-jbang/camel-jbang-it tests locally with:

mvn verify -B -Djbang-it-test -Dcamel-cli.instance.type=local-camel-cli-process -Dit.test=ExportITCase

ExportITCase results: 11 tests run, 0 failures, 0 errors, 2 skipped (the skipped tests require custom Quarkus system properties or container-only tags).

All export scenarios pass — Spring Boot, Quarkus, Camel Main, export with files, export with agent, export with JMX management, export with CLI connector, and export with Camel config.

@gnodet gnodet force-pushed the CAMEL-21208-freemarker-templates branch from 696d7c8 to 8a25f22 Compare April 9, 2026 15:27
@github-actions github-actions bot removed the docs label Apr 9, 2026
@gnodet
Copy link
Copy Markdown
Contributor Author

gnodet commented Apr 9, 2026

Claude Code on behalf of Guillaume Nodet

CI failures are unrelated to this PR — camel-langchain4j-embeddings LangChain4jEmbeddingsComponentInfinispanTargetIT fails with Infinispan SocketTimeoutException (flaky infra test). The camel-jbang-core module was never reached due to the early failure. Needs a rerun.

gnodet and others added 5 commits April 9, 2026 21:12
…ker templates in camel-jbang

- Add FreeMarker 2.3.34 dependency to camel-jbang-core
- Create TemplateHelper utility using square bracket syntax ([=var], [#if]...[/#if])
  to avoid conflicts with ${...} (Maven) and <...> (XML) in generated content
- Convert all 23 .tmpl template files to .ftl FreeMarker templates
- Refactor Export*, Run, and Init commands to use TemplateHelper instead of
  manual StringBuilder/replaceAll/replaceFirst code generation
- Extract shared helpers (buildRepositoryList, buildDependencyList, formatBuildProperties,
  mavenGavComparator) into ExportBaseCommand
- Maintain backward compatibility for catalog-provided templates in ExportSpringBoot
- Remove 4 unreferenced templates (main-docker-*.tmpl, main-jkube-pom.tmpl)
- Keep deprecated bind templates (.tmpl) used by TemplateProvider

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add backward compat check for old .tmpl catalog template name in ExportSpringBoot
- Remove dead model variables (CamelVersion, QuarkusManagementPort)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove unnecessary bare block in Run.generateOpenApi (leftover from try-with-resources)
- Deduplicate model building in Export.copyDockerFiles

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comprehensive test coverage for all 23 FreeMarker templates:
- FreeMarker-processed templates (processTemplate): code-java, main,
  spring-boot-main, Dockerfile21/25, readme, readme.native,
  rest-dsl.yaml, run-custom-camel-version, main-pom (with deps,
  repos, jib/jkube), spring-boot-pom, quarkus-pom
- Init templates (raw text loading): java, yaml, xml, kamelet
  source/sink/action, pipe, integration

Tests verify: license header stripping, placeholder resolution,
conditional rendering, list iteration, Maven ${} passthrough,
Kamelet {{}} passthrough, and missing template error handling.

Also regenerate jbang command docs after rebase.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet gnodet force-pushed the CAMEL-21208-freemarker-templates branch from 8a25f22 to c482a0d Compare April 9, 2026 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants