vertx-web
vertx-web copied to clipboard
Update Templates documentation for Thymeleaf to say RoutingContext object cannot be accessed directly
Version
v4.0.3
Context
The RoutingContext object is not accessible in Thymeleaf templates, which is contrary to the vertx-web documentation.
Using something like context.normalizedPath()
in a template results in the following error -
14:19:10.530 [vert.x-eventloop-thread-1] ERROR org.thymeleaf.TemplateEngine - [THYMELEAF][vert.x-eventloop-thread-1] Exception processing template "templates/index.html": Exception evaluating OGNL expression: "context.normalizedPath()"
...
Caused by: java.lang.NullPointerException: target is null for method normalizedPath
- The TemplateEngine apidocs only allow a JsonObject or Map<String, Object> to be passed to the
render
method - TemplateHandler passes
RoutingContext.data()
to therender
method (casted to a JsonObject) - this (I think) only allows access to values that were added to the context explicitly byRoutingContext.put(key, value)
, so request params,normalizedPath
, even usingRoutingContext.get(key)
does not work.
So is it necessary to update the vertx-web docs for Thymeleaf templates to reflect this? I think the Handlebars docs gets this correct. (If the context object is indeed accessible, please let me know what I have misunderstood!)
Do you have a reproducer?
- There is a StackOverflow question about this issue here
- Additionally, there is a discussion on the Vert.x Google group that speaks about this
The Google group link mentions how to actually be able to use the context object in Thymeleaf, by passing Map<String, Object>
to the engine. I will provide an example here to help anyone out.
Vert.x code
router.get("/").handler(ctx -> {
Map<String, Object> mappy = new HashMap<String, Object>();
ctx.put("hello", "ola");
mappy.put("context", ctx);
mappy.put("hello", "bonjour");
engine.render(mappy, "templates/index.html").onSuccess(buff -> ctx.end(buff));
});
The RoutingContext
object has a key-value put into it. The entire context object is then put as a value into the Map<String, Object>, with key being context
. Another key-value is put into the Map.
Thymeleaf template
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Good Thymes Virtual Grocery</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="${context.normalizedPath()}"></p>
<p th:text="${hello}"></p>
<p th:text="${context.get('hello')}"></p>
</body>
</html>
In the template
- The first variable must resolve to
/
- The second variable must resolve to
bonjour
- The third variable must resolve to
ola
Result
@ThorodanBrom yes, this is an old issue we haven't had the time to address yet. The behavior across engines is not standard. We would like to get all engines to work the same way, so probably we need to update the documentation on all engines to state that the data on context.data()
is exposed, that caching works consistently across all engines, and that template file resolution too.
Feel free to spot all the inconsistencies on the documentation and report then, so a pull request can later address some or all the issues.
Hello @pmlopes
Many thanks for the clarification. Sorry for the delay as well. I have gone through the latest Vert.x Web documentation (v4.3.1) and have listed out all the inconsistencies in the Templates docs for different engines.
MVEL template engine
-
Incorrectly states that
RoutingContext
is available in the template- Should be updated to mention that
RoutingContext.data()
is available in the template when usingTemplateHandler
- Should be updated to mention that
Jade template engine
-
Incorrectly states that
RoutingContext
is available in the template when using TemplateHandler- Should be updated to mention that
RoutingContext.data()
is available in the template when usingTemplateHandler
- Should be updated to mention that
Handlebars template engine
-
Correctly states that only
RoutingContext.data()
is available in the template when using TemplateHandler - However, since
RoutingContext.data()
is cast to a JsonObject, is there any restriction on the kind of objects that can be included inRoutingContext.data()
? If yes, should they be mentioned in the docs?
Thymeleaf template engine
-
Incorrectly states that
RoutingContext
is available in the template when using TemplateHandler
Apache FreeMarker template engine
-
Incorrectly states that
RoutingContext
is available in the template when using TemplateHandler- Should be updated to mention that
RoutingContext.data()
is available in the template when usingTemplateHandler
- Should be updated to mention that
Pebble template engine
-
Incorrectly states that
RoutingContext
is available in the template when using TemplateHandler- Should be updated to mention that
RoutingContext.data()
is available in the template when usingTemplateHandler
- Should be updated to mention that
Rocker template engine
- No mention of TemplateHandler, example uses
engine.render()
directly - Gives an example of passing JSON object to
engine.render()
HTTL template engine
- No mention of TemplateHandler, example uses
engine.render()
directly - Gives an example of passing JSON object to
engine.render()
Rythm template engine
- No mention of TemplateHandler, example uses
engine.render()
directly - Gives an example of passing JSON object to
engine.render()
JTE template engine (Not documented)
- Not documented in Vert.x Web docs
I've tried to list out the various templates and whether they can can cache templates or not, but I could not understand which engines are caching templates when reading the code.
If there's anything else that I can do to help, please let me know.
Hello any update about this still wrong documentation in v4.5.1
Thanks for the heads-up @mikadev , will do my best to fix this in 4.5.2
Fixed by #2584