You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
One repository, seven flat modules, one version. A consumer sees only jmsfx-core and one generated library, but a change to the Browse page bumps the version they pin.
The original plan here was to split into separate repositories. That is the wrong shape for this project: almost every issue in 1.5.0 was cross-cutting — #68 touched fragments, model and generated code; #78, #79 and #80 touched all three across both libraries; #90 touched generator, server and standard. Split, each of those becomes a sequence of coordinated pull requests with version bumps in between. #106 is the evidence in the other direction: bringing jmsfx-halluxin made things simpler, and the fragment checks now cover both trees precisely because they share a repository.
So: one repository, grouped by deliverable, with lifecycles that can move independently.
Six top-level modules
module
contains
what it is
jmsfx-core
—
the API. Everything pins it, so it should move slowly
jmsfx-tools
jmsfx-generator, jmsfx-editor
build-time tooling: produces libraries, and edits the models they come from
jmsfx-viewer
jmsfx-creator, jmsfx-server
applications, consuming a library like anyone else
jmsfx-standard
—
the generated APP-6E library
jmsfx-hallux
—
the hallux extension library
jmsfx-battleorder
—
the Battle Order extension library, moving in from its own repository
jmsfx-tools and jmsfx-viewer are parent and aggregator poms for their children, which is what makes the grouping do real work: within a group ${project.version} still applies, so the generator and the editor move together as one thing; between groups a dependency pins an explicit released version, so bumping it is a decision.
The editor belongs with the generator rather than with the applications because it edits the model file, which is the generator's input. The dependency graph hides that — the coupling runs through the YAML, and #7 is what will make it explicit.
What crosses a boundary
module
depends on
jmsfx-standard, jmsfx-hallux, jmsfx-battleorder
jmsfx-core
tools / jmsfx-editor
jmsfx-core, and jmsfx-generator in-group
viewer / jmsfx-creator
jmsfx-core, a library at runtime
viewer / jmsfx-server
a library — #93, still a hard compile dependency on jmsfx-standard
So jmsfx-core's version is pinned in four or five places. That is the deliberate bump this is for.
The cost, stated plainly
Once jmsfx-standard declares jmsfx-core:2.0.0 rather than ${project.version}, Maven resolves that exact GAV and will not substitute the 2.1.0-SNAPSHOT beside it in the tree. That is what lifecycle independence means — but it follows that a change to core is no longer tested against standard until standard's dependency is deliberately bumped, and mvn verify at the root stops proving the tree is coherent.
Fair when cadences differ. Pure overhead when they do not. So do not split every lifecycle at once: the signal is a module that is stable while others churn, and jmsfx-core is the obvious first, being the API everything pins.
Mechanics
Directory moves plus a three-level parent chain, both unremarkable.
Today's pom.xml is both parent and aggregator. Separating them lets the parent sit on a stable version of its own, so bumping it does not mean editing five <parent><version> blocks.
Release tags per module — jmsfx-core-2.0.0 — with workflows triggered on tag patterns publishing only that module.
If jmsfx-generator publishes, jmsfx-tools must publish too, or resolution breaks for exactly the reason the root parent does. Same trap as Publish jmsfx to Maven Central from the release workflow #103's parent. excludeArtifacts becomes jmsfx-editor, jmsfx-viewer, jmsfx-creator, jmsfx-server, with jmsfx-generator coming off the list.
One build product per library
jmsfx-creator and jmsfx-server no longer compile against any library (#76, #93), so which one they ship with is a packaging decision. Each gets a Maven profile per library, and each profile produces a distinct artifact, distinguished by classifier — one build product per library rather than one artifact whose contents depend on how it was built.
Two things settled while working out how:
No activeByDefault. A default-activated profile is switched off the moment any other profile is named on the command line, and #103 put mvn -Prelease deploy in the release workflow. A standard profile relying on default activation would silently deactivate during a release and publish a server with no library in it. The failure is quiet and late: the jar starts, then answers 500 to every request with "No IconLibrary on the classpath". So the library is always named explicitly — -Pstandard, -Phallux, -Pbattleorder — and a build that names none should fail rather than guess.
runtime, not runtime + optional.spring-boot:repackage leaves optional dependencies out of BOOT-INF/lib, so an optional library never reaches the fat jar. optional is the wrong tool regardless — it stops a dependency reaching consumers, and nothing consumes an application as a library. runtime alone is what prevents anything compiling against it. See #93.
The deployment then becomes one instance per library on its own *.ctg.co.nz subdomain, each running the artifact carrying its classifier. #111 is what makes that verifiable from outside: today a running instance cannot say which library it has.
Not a reason to do this
A consumer pinned to jmsfx-core:2.0.0 is already fully insulated from later work, whatever the repository looks like. The shared version costs a version number that moves without content changing — cosmetic, not a stability problem. The pain that prompted this was jmsfx-hallux depending on jmsfx-core:1.5.0-SNAPSHOT, and a snapshot means "whatever is in the reactor right now". #103 gave it something to pin and #106 put it where it can.
Prerequisites
Stop jmsfx-hallux depending on jmsfx-creator #109 — done. jmsfx-hallux no longer depends on jmsfx-creator; a library depending on an application is invisible under a shared version and wrong under split ones.
Where the SVG fragments live. jmsfx-standard and jmsfx-hallux each carry a full copy — 2,972 and 3,286, the shared ones byte-identical — and jmsfx-battleorder will want them too. One repository makes that visible and puts both under the same checks, but does not fix it. #82 does, by injecting fragments into the generated classes so a library carries what it needs.
One repository, seven flat modules, one version. A consumer sees only
jmsfx-coreand one generated library, but a change to the Browse page bumps the version they pin.The original plan here was to split into separate repositories. That is the wrong shape for this project: almost every issue in 1.5.0 was cross-cutting — #68 touched fragments, model and generated code; #78, #79 and #80 touched all three across both libraries; #90 touched generator, server and standard. Split, each of those becomes a sequence of coordinated pull requests with version bumps in between. #106 is the evidence in the other direction: bringing
jmsfx-halluxin made things simpler, and the fragment checks now cover both trees precisely because they share a repository.So: one repository, grouped by deliverable, with lifecycles that can move independently.
Six top-level modules
jmsfx-corejmsfx-toolsjmsfx-generator,jmsfx-editorjmsfx-viewerjmsfx-creator,jmsfx-serverjmsfx-standardjmsfx-halluxjmsfx-battleorderjmsfx-toolsandjmsfx-viewerare parent and aggregator poms for their children, which is what makes the grouping do real work: within a group${project.version}still applies, so the generator and the editor move together as one thing; between groups a dependency pins an explicit released version, so bumping it is a decision.The editor belongs with the generator rather than with the applications because it edits the model file, which is the generator's input. The dependency graph hides that — the coupling runs through the YAML, and #7 is what will make it explicit.
What crosses a boundary
jmsfx-standard,jmsfx-hallux,jmsfx-battleorderjmsfx-corejmsfx-editorjmsfx-core, andjmsfx-generatorin-groupjmsfx-creatorjmsfx-core, a library at runtimejmsfx-serverjmsfx-standardSo
jmsfx-core's version is pinned in four or five places. That is the deliberate bump this is for.The cost, stated plainly
Once
jmsfx-standarddeclaresjmsfx-core:2.0.0rather than${project.version}, Maven resolves that exact GAV and will not substitute the2.1.0-SNAPSHOTbeside it in the tree. That is what lifecycle independence means — but it follows that a change to core is no longer tested against standard until standard's dependency is deliberately bumped, andmvn verifyat the root stops proving the tree is coherent.Fair when cadences differ. Pure overhead when they do not. So do not split every lifecycle at once: the signal is a module that is stable while others churn, and
jmsfx-coreis the obvious first, being the API everything pins.Mechanics
pom.xmlis both parent and aggregator. Separating them lets the parent sit on a stable version of its own, so bumping it does not mean editing five<parent><version>blocks.jmsfx-core-2.0.0— with workflows triggered on tag patterns publishing only that module.jmsfx-generatorpublishes,jmsfx-toolsmust publish too, or resolution breaks for exactly the reason the root parent does. Same trap as Publish jmsfx to Maven Central from the release workflow #103's parent.excludeArtifactsbecomesjmsfx-editor,jmsfx-viewer,jmsfx-creator,jmsfx-server, withjmsfx-generatorcoming off the list.One build product per library
jmsfx-creatorandjmsfx-serverno longer compile against any library (#76, #93), so which one they ship with is a packaging decision. Each gets a Maven profile per library, and each profile produces a distinct artifact, distinguished by classifier — one build product per library rather than one artifact whose contents depend on how it was built.Two things settled while working out how:
No
activeByDefault. A default-activated profile is switched off the moment any other profile is named on the command line, and #103 putmvn -Prelease deployin the release workflow. Astandardprofile relying on default activation would silently deactivate during a release and publish a server with no library in it. The failure is quiet and late: the jar starts, then answers 500 to every request with "No IconLibrary on the classpath". So the library is always named explicitly —-Pstandard,-Phallux,-Pbattleorder— and a build that names none should fail rather than guess.runtime, notruntime+optional.spring-boot:repackageleaves optional dependencies out ofBOOT-INF/lib, so an optional library never reaches the fat jar.optionalis the wrong tool regardless — it stops a dependency reaching consumers, and nothing consumes an application as a library.runtimealone is what prevents anything compiling against it. See #93.The deployment then becomes one instance per library on its own
*.ctg.co.nzsubdomain, each running the artifact carrying its classifier. #111 is what makes that verifiable from outside: today a running instance cannot say which library it has.Not a reason to do this
A consumer pinned to
jmsfx-core:2.0.0is already fully insulated from later work, whatever the repository looks like. The shared version costs a version number that moves without content changing — cosmetic, not a stability problem. The pain that prompted this wasjmsfx-halluxdepending onjmsfx-core:1.5.0-SNAPSHOT, and a snapshot means "whatever is in the reactor right now". #103 gave it something to pin and #106 put it where it can.Prerequisites
jmsfx-halluxno longer depends onjmsfx-creator; a library depending on an application is invisible under a shared version and wrong under split ones.jmsfx-serveris library-agnostic: one icon controller resolving against the discovered library, and 23 per-symbol-set controllers gone.Still open
Where the SVG fragments live.
jmsfx-standardandjmsfx-halluxeach carry a full copy — 2,972 and 3,286, the shared ones byte-identical — andjmsfx-battleorderwill want them too. One repository makes that visible and puts both under the same checks, but does not fix it. #82 does, by injecting fragments into the generated classes so a library carries what it needs.Related: #7, #81, #82, #93, #101, #103, #106, #108, #109, #111.