JAR dependencies never reached the classpath; $Total = 5; now parses (formula1 findings §11–§13) - #111
Merged
Merged
Conversation
…y skipping `ALTER MODULE X ADD JAR DEPENDENCY (…)` wrote the coordinate, `list jar dependencies` reported it, the build went green — and the runtime threw "No JDBC driver found in app for URL". Nothing between the author and the runtime said the jar was never fetched. The write was never wrong. Declaring and resolving are separate steps: `mx sync-java-dependencies <project.mpr>` downloads into vendorlib/, Studio Pro runs it when you edit Module Settings, and nothing ran it headless. Measured on 11.12.1: a full `mxbuild --target=deploy` emits a build.gradle with no dependencies block and downloads nothing; the sync command then fetches the jar. (The open question in the report was whether mxbuild skips Maven resolution or mxcli writes somewhere MxBuild cannot read — neither.) Wired at three levels so the gap cannot stay silent: the executor says so the moment it writes a coordinate that is not in vendorlib/, `mxcli sync-java-deps` does the resolution on demand (`--check` exits non-zero as a build gate), and `run --local` vendors anything missing before boot, so the warm loop works from a fresh clone. Resolution needs network, so each call site is best-effort and names the command to retry. Falling back to another version's mx is now stated rather than silent — a version mismatch otherwise surfaces as an mpr-format complaint that reads like a corrupt project. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
`$Total = 5;` failed with "no viable alternative at input '$Total=5'" while `DECLARE $Total Integer = 0;` worked — and so did every other assignment in MDL: `$X = HEAD($List)`, `$X = create M.E (…)`, `$X = execute database query …`. Assignment existed only as a prefix on specific activity statements, plus a `SET $Var = expression` statement, so a plain value needed a keyword that nothing in the error or the surrounding syntax suggested. Rather than improve the error, make the form people reach for work. SET is now optional; both spellings produce the same MfSetStmt and the same ChangeVariableAction, and the keyword form is untouched. Checked for regressions with a control binary rather than by reading the grammar: stash the .g4, regenerate, build bin/mxcli-control, and sweep every script in mdl-examples with both. Thirteen fail — the same thirteen, all pre-existing. ANTLR's adaptive prediction picks the activity-prefixed alternatives on its own; no reordering was needed. Executed against a real .mpr, mxbuild reports 0 errors. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
`mxcli test tests/ -p app/App.mpr` failed with "no such file or directory" for a tests/ sitting right next to the .mpr. Resolving against the process CWD is defensible on its own, but mxcli otherwise encourages naming the project rather than standing in its directory, so the two conventions collide and the failure reads as a missing directory. The fallback applies only when the CWD-relative path does not exist. A tests/ in both places still resolves to the one the user is standing in — silently preferring the project's copy would run the wrong suite — and a path that exists in neither is passed through unchanged, so the error names what was typed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
A `dynamic` SQL override still requires a value for every parameter the query
*definition* declares, including ones the replacement SQL never mentions — the
parameter list belongs to the definition, not to the string. And a `{param}`
placeholder can be concatenated into a path, which is what keeps an absolute
path out of the model: bind the data directory as a constant and build the file
name around it.
Both come from a DuckDB read path verified end to end on Mendix 11.13, which
also settles the open question about `type 'BYOD'` — the runtime accepts it, not
just the editor.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #110, covering the sections added to the formula1 findings after that PR was opened (§11 DuckDB read path, §12 JAR dependencies, §13 MDL papercuts). Verified against real MxBuild on Mendix 11.12.1.
The silent one: a declared JAR dependency never reached the classpath
ALTER MODULE X ADD JAR DEPENDENCY (…)wrote the coordinate,list jar dependenciesreported it, the build went green — and the runtime threwSQLException: No JDBC driver found in app for URL.deployment/build.gradlehad no dependencies block and the jar was nowhere in the project.The write was never wrong. Declaring and resolving are separate steps:
mx sync-java-dependencies <project.mpr>downloads intovendorlib/, Studio Pro runs it when you edit Module Settings, and nothing ran it headless.That answers the open question in the report — it is neither "mxbuild skips Maven resolution" nor "mxcli writes somewhere MxBuild cannot read". Measured both halves on 11.12.1: a full
mxbuild --target=deployresolves nothing, and the sync command then putscommons-lang3-3.14.0.jarinvendorlib/. Found bystrings mx.dll | grep -i dependencsurfacingISyncJavaDependenciesRunner/SkipManagedDependencySync, then confirming inmx --help.Wired at three levels so the gap cannot stay silent again:
vendorlib/, naming the command to run;mxcli sync-java-depsresolves on demand, and--checkreports what is missing and exits non-zero, so it works as a build gate;run --localvendors anything missing before boot, so the warm loop works from a fresh clone.Resolution needs network, so every call site is best-effort and prints the retry command rather than failing the run. It sits before the database check, since resolving jars has nothing to do with a database.
A test caught a second problem while I was writing it: resolution silently fell back to a different Mendix version's
mx. That fallback is still there (a newer mx reads an older project fine) but is now stated — otherwise the mismatch surfaces as an mpr-format complaint that reads like a corrupt project.$Total = 5;now parsesIt failed with
no viable alternative at input '$Total=5'whileDECLARE $Total Integer = 0;worked — and so did$X = HEAD($List),$X = create M.E (…)and$X = execute database query …. Assignment existed only as a prefix on specific activity statements, plus aSET $Var = expressionstatement, so a plain value needed a keyword that nothing in the error or the surrounding syntax suggested.SETis now optional. Both spellings produce the sameMfSetStmtand the sameChangeVariableAction; the keyword form is untouched.Regressions were checked with a control binary rather than by reading the grammar: stash the
.g4, regenerate, buildbin/mxcli-control, and sweep every script inmdl-exampleswith both. Thirteen fail — the same thirteen, all pre-existing. ANTLR's adaptive prediction picks the activity-prefixed alternatives on its own, so no reordering was needed. Executed against a real.mpr, mxbuild reports 0 errors.Smaller ones
mxcli test tests/ -p app/App.mprno longer fails for atests/sitting next to the.mpr. The fallback to project-relative applies only when the CWD-relative path does not exist — atests/in both places still resolves to the one you are standing in, since silently preferring the project's copy would run the wrong suite, and a path that exists in neither is passed through so the error names what was typed.type 'BYOD'is confirmed at runtime, not just in the editor (§11), so the skill no longer hedges. Added the twodynamicquery rules that cost time: a dynamic override still requires a value for every parameter the query definition declares, including ones the replacement SQL ignores; and a{param}placeholder concatenates into a path, which is what keeps an absolute path out of the model.Nothing to do
mxcli lint's MDL044 message was singled out as the best error text in the tool. Left exactly as it is.Verification
cmd/mxcli/docker/javadeps_test.go,mdl/visitor/visitor_microflow_bare_assign_test.go(the bare and keyword forms must agree on the AST, not merely both parse),cmd/mxcli/cmd_test_run_paths_test.go.run --local --setup→ jar invendorlib/; and--checkexits 1 when one is missing, 0 when not.mdl-examples/bug-tests/f1-13-bare-variable-assignment.mdlexecutes against a real.mprand builds 0 errors.mainafter Published OData services could not build from MDL; JAR dependencies never resolved; init/settings/grammar fixes (formula1 findings) #110 merged; grammar regenerated,go build ./...clean, fullgo test ./...green..claude/skills/fix-issue.md.🤖 Generated with Claude Code
https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
Generated by Claude Code