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
ViewDispatches gates a Spring entrypoint's String-returning method into the view-name tier whenever the owning type (or method) is flagged with the spring entrypoint framework. That flag doesn't distinguish @RestController from @Controller, and doesn't check @ResponseBody on @Controller methods either — so a REST endpoint's return value (an HTTP response body) gets analyzed as if it names a view template.
Found while fixing the crash in #271 (a non-identifier target in this same code path threw an NPE); this is the "related semantic issue" called out but intentionally not fixed in that PR, since it changes detection scope rather than just the crash.
Where
SpringEntrypointFinder.isEntrypointClass matches on substring, so both annotations set the same spring framework tag:
if (annotation.getNameAsString().contains("RestController")
|| annotation.getNameAsString().contains("Controller")
|| ...
Summary
ViewDispatchesgates a Spring entrypoint'sString-returning method into the view-name tier whenever the owning type (or method) is flagged with thespringentrypoint framework. That flag doesn't distinguish@RestControllerfrom@Controller, and doesn't check@ResponseBodyon@Controllermethods either — so a REST endpoint's return value (an HTTP response body) gets analyzed as if it names a view template.Found while fixing the crash in #271 (a non-identifier target in this same code path threw an NPE); this is the "related semantic issue" called out but intentionally not fixed in that PR, since it changes detection scope rather than just the crash.
Where
SpringEntrypointFinder.isEntrypointClassmatches on substring, so both annotations set the samespringframework tag:(
src/main/java/com/ibm/cldk/javaee/spring/SpringEntrypointFinder.java)ViewDispatches.collectTypesthen uses that same undifferentiated tag to gate thereturnsite:(
src/main/java/com/ibm/cldk/artifacts/ViewDispatches.java)Reproducer
Robot Shop's
shippingservice is a concrete real-world example (Controller.java):Both
health()andcount()are REST response bodies, not view names, but both currently create aview-namedispatch site:health()'s"OK"closes as a literal and (if any artifact happens to match) would produce a confident-wrongJ_DISPATCHES_TOedge.count()'sString.valueOf(count)isn't a literal or bare identifier, so it (correctly, after fix(artifacts): a non-identifier view-dispatch target is not a dataflow variable, not a NullPointerException #271) ends upunresolvedwith reasonnon-literal— but it shouldn't have been considered a candidate site at all.The same gap applies to
@Controllermethods annotated@ResponseBody:Expected
ViewDispatchesshould not create aview-namesite for:@RestController, and@ResponseBody.Ordinary
@Controllerview-returning methods (return "home";, dataflow-traced locals, etc.) should keep working exactly as they do today.Suggested regression tests
@RestController+ literal return (return "OK";) → noview-namesite at all.@RestController+ non-identifier return (return String.valueOf(n);) → noview-namesite (currently ends up correctly unresolved post-fix(artifacts): a non-identifier view-dispatch target is not a dataflow variable, not a NullPointerException #271, but ideally isn't a site in the first place).@Controller+@ResponseBody+ literal return → noview-namesite.@Controller+ literal return, no@ResponseBody→ existing view-name behavior unchanged.@Controller+ dataflow-traced local return (String page = "home"; return page;) → existing dataflow-based view resolution unchanged.