I'm trying to create a dashboard application where multiple widgets get updates through SSE. My DashboardController looks like:
public class DashboardController
{
private WidgetService widgetService;
public DashboardController(WidgetService widgetService)
{
this.widgetService = widgetService;
}
@GetMapping("/")
public String index(final Model model)
{
for(WidgetInterface<?> widget : widgetService.getAll()) {
model.addAttribute("widget-data-driver-" + widget.getIdentifier(),
new ReactiveDataDriverContextVariable(widget.getInitialData(), 100));
}
model.addAttribute("widgets", widgetService.getAll());
return "index";
}
}
And my WidgetInterface:
public interface WidgetInterface<T>
{
public String getIdentifier();
public String getTitle();
public String getStreamEndpoint();
public Flux<T> getInitialData();
public Map<String, String> getColumns();
public String getThymeLeafFraction();
public Date getLastItemDate();
public Flux<T> getItemsUpdatedSince(Date date);
}
All is working fine for one widget (from the WidgetService). I'm trying to pass a ReactiveDataDriverContextVariable
for each widget to Thymeleaf. But I get the following error:
org.thymeleaf.exceptions.TemplateProcessingException: Only one data-driver variable is allowed to be specified as a model attribute, but at least two have been identified: 'widget-data-driver-nufeed' and 'widget-data-driver-weatherapi'
I have two active widgets, one is an RSS feed an one implements weather api. I understand the error, but how to can I set up the reactive variables for multiple widgets?
Update answer based on Angelos comment (2022)
I tried to replace the DashboardController.index method with:
GetMapping("/")
public String index(final Model model, Authentication authentication)
{
setAuthentication(authentication);
Flux<WidgetInterface<?>> flux = Flux.just(widgetService.getAll().toArray(new WidgetInterface<?>[0]));
model.addAttribute("widgets", new ReactiveDataDriverContextVariable(flux));
return "index";
}
This is working, except for the fact that now I cannot iterate over my widget.getInitialData() in thymeleaf (this is a fraction file as described above):
<div data-th-each="item : ${widget.getInitialData()}" th:data-id="@{${item.id}}" id="art">
<a th:data-lightbox="'' + ${widget.identifier}" th:href="${item.image}">
<img th:src="'https://images.weserv.nl/?url=' + ${item.image} + '&w=200&h=200&fit=cover&a=top'" th:data-lightbox="'' + ${widget.identifier}"
class="rounded d-block user-select-none" style="max-height:100px;max-width:150px;margin-right:10px;" align="left" />
</a>
<h5 th:text="${item.description}" class="card-title"></h5>
</div>
This gives this error:
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "item.id" (template: "art_fraction" - line 1, col 56)
at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:292) ~[thymeleaf-spring5-3.0.15.RELEASE.jar:3.0.15.RELEASE]
ReactiveDataDriverContextVariable
can contain aFlux
of object; so I guess you should change your code by passing just 1ReactiveDataDriverContextVariable
with a stream of objects – AssumingReactiveDataDriverContextVariable
for each Flux object, except there can only be one per template. See my question for the error and what I have tried. – Centerboard