Skip to content

feat(java): trace Spring/MyBatis enterprise flow end-to-end (#389)#468

Merged
colbymchenry merged 1 commit into
mainfrom
feat/spring-mybatis-389
May 26, 2026
Merged

feat(java): trace Spring/MyBatis enterprise flow end-to-end (#389)#468
colbymchenry merged 1 commit into
mainfrom
feat/spring-mybatis-389

Conversation

@colbymchenry
Copy link
Copy Markdown
Owner

Summary

Closes the three threads of #389 so an agent can trace HTTP route → @Controller → field-injected service → impl → DAO/Mapper → MyBatis XML SQL end-to-end on real Spring + MyBatis projects, with no Read/Grep fallback.

  • Field-injected concrete-bean trace. Java this.<field>.method() is unwrapped at extraction (was emitted verbatim as this.userbo.method and dropped through every name-matcher strategy). The receiver name is then looked up in the enclosing class's field declarations to get the declared type and resolve the method on it — closes the controller→bean hop when the field name doesn't capitalize to the type (userboUserBO). General Java fix, not Spring-specific.
  • MyBatis XML mapper as a first-class language. New mybatis-extractor.ts parses <mapper namespace="..."><select|insert|update|delete|sql id="X"> and emits method-shaped nodes qualified <namespace>::<id>, plus <include refid="X"/> refs to <sql> fragments. Non-mapper XML (pom, log4j, web.xml) → file node only. New mybatisJavaXmlEdges synthesizer joins Java mapper methods to XML statements by suffix-matching qualified names; ambiguous simple-name collisions dropped for precision.
  • Spring @Value / @ConfigurationProperties → application config. application.{yml,yaml,properties} + profile variants parse on the framework path; each leaf key becomes a constant node qualified by its dotted path. @Value("${k}") / @Value("${k:default}") and @ConfigurationProperties(prefix="X") emit binding nodes resolved with Spring's relaxed binding (kebab↔camel↔snake).

Validation

Real-world repo: macrozheng/mall-tiny (Spring MVC + MyBatis Plus).

Full chain trace(UmsRoleController.listResource → UmsResourceMapper.getResourceListByRoleId-xml) connects across 5 hops via static + synthesized edges. 11/11 @Value annotations resolve (incl. @ConfigurationProperties(prefix="secure.ignored")); 6/6 custom-SQL mapper methods bridge to XML.

Test plan

  • Repro the issue's exact example (UserAction @Resource(name="userBO") UserBO) on a temp Spring project — confirm UserAction.toLogin2 → UserBO.toLogin2 edge appears (was missing)
  • 4 new integration tests in __tests__/frameworks-integration.test.ts (bean injection, MyBatis bridge, @Value/relaxed binding, non-MyBatis XML noise-free)
  • Full test suite: 1005 passed, 0 new failures
  • End-to-end flow on mall-tiny: controller → service-iface → impl → mapper-iface → XML

Docs

  • CHANGELOG.md [Unreleased] entry (Added section)
  • docs/design/dynamic-dispatch-coverage-playbook.md matrix row + narrative

Closes #389.

🤖 Generated with Claude Code

Closes three gaps that broke `trace(controller, mapper-xml)` on real Spring +
MyBatis projects:

1. **Field-injected concrete-bean trace.** Java `this.<field>.method()` is
   unwrapped at extraction (was surfaced as `this.<field>.method` and dropped
   through every name-matcher strategy). The receiver name is then looked up
   in the enclosing class's field declarations to get the declared type and
   resolve the method on it. Closes the controller→bean hop when the field
   name doesn't capitalize to the type (`userbo` → `UserBO`). General Java
   fix, not Spring-specific.

2. **MyBatis XML mapper as a first-class language.** New extractor parses
   `<mapper namespace="..."><select|insert|update|delete|sql id="X">` and
   emits method-shaped nodes qualified as `<namespace>::<id>`, plus
   `<include refid="X"/>` references to `<sql>` fragments. Non-mapper XML
   (pom, log4j, web.xml) → file node only. A new synthesizer
   (`mybatisJavaXmlEdges`) joins Java mapper methods to XML statements by
   suffix-matching qualified names. Ambiguous simple-name collisions dropped
   for precision.

3. **Spring `@Value`/`@ConfigurationProperties` → application config.**
   `application.{yml,yaml,properties}` + profile variants parse on the
   framework path; each leaf key becomes a `constant` node qualified by its
   dotted path. `@Value("${k}")` / `@Value("${k:default}")` and
   `@ConfigurationProperties(prefix="X")` emit binding nodes that resolve
   with Spring's relaxed binding (kebab↔camel↔snake).

Validated on macrozheng/mall-tiny: full chain
`UmsRoleController.listResource → UmsRoleService.listResource → impl →
UmsResourceMapper.getResourceListByRoleId → XML <select>` connects across 5
hops via static + synthesized edges. 11/11 @value annotations resolved
(incl. `@ConfigurationProperties(prefix="secure.ignored")`); 6/6 custom-SQL
mapper methods bridge to XML.

Tests: 4 new integration tests in frameworks-integration.test.ts. Full
suite: 1005 passed.

Docs: CHANGELOG `[Unreleased]` entry + dynamic-dispatch-coverage-playbook
narrative + matrix row.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhance enterprise Java/Spring flow coverage: MyBatis XML, config keys, and field-injected bean traces

1 participant