Skip to main content

Designing a Multi-Framework Portability Test with a Vending Machine Domain

· 3 min read
TeaQL Team
Core Team

TeaQL aims to keep domain models and generated business APIs independent of the web framework. The vending-machine-service example gives us a concrete way to test that claim across Spring Boot, Quarkus, and Micronaut.

This article defines what the portability test must prove and separates architectural intent from verified evidence.

The Setup

The test starts with one vending.xml model describing machines, products, inventory, transactions, and orders.

It then generates three separate web applications:

  1. 005-vending-machine-web-spring-boot;
  2. 006-vending-machine-web-quarkus;
  3. 007-vending-machine-web-micronaut.

The test may point all three applications at an isolated PostgreSQL schema to compare behavior. That shared schema is a test fixture, not a recommendation that independently deployed services share one production database.

A Shared Core

At the heart of the test is the java-lib-core module. The entities, expressions, checkers, and UserContext contract should be generated from the same model for every framework target.

Generated SmartList, SearchRequest, and expression APIs give each application the same domain vocabulary. Portability does not mean that the complete application outputs are byte-for-byte identical: HTTP routing, dependency injection, configuration, and lifecycle code remain framework-specific.

Framework Adaptation

The framework adapters follow distinct lifecycle and dependency-injection models:

  • In Spring Boot, the intended runtime path uses SpringJdbcSqlExecutor with NamedParameterJdbcTemplate.
  • In Quarkus, the intended path uses the framework-neutral teaql-provider-jdbc adapter with an Agroal data source and CDI producers.
  • In Micronaut, the intended path uses the same JDBC adapter with @Singleton bean definitions and the configured JDBC data source.

What the Test Must Verify

A useful portability test needs more than successful generation. Each target must pass the same gates:

  1. evaluate the shared model with no blocking diagnostics;
  2. generate the domain core and selected web target;
  3. compile and run the generated tests on Java 21;
  4. start against a clean PostgreSQL test schema;
  5. execute the same intent-declared read;
  6. execute the same .audit_as() mutation;
  7. compare persisted state, API response, and audit output;
  8. preserve the commands and logs as evidence.

The framework-specific code is allowed to differ. The test fails when those differences leak into domain behavior or require hand-editing generated entities.

Current Evidence

The TeaQL service catalog inspected on 2026-07-13 advertised java-web-spring-boot, java-web-quarkus, and java-web-micronaut. Catalog presence proves target discoverability, not a clean build.

The same repository verification found generator/runtime alignment blockers in the Java core output. Until each application has a preserved clean-build and runtime smoke-test report, we should describe this as the portability test design and target architecture, not as a completed end-to-end validation.

Current verified combinations and blockers are tracked in the compatibility matrix. Once all three targets pass the gates above, the vending-machine test can provide meaningful evidence that teams may change framework adapters without rewriting their generated domain contract.