I’m currently upgrading the dependencies on a company project, and thymeleaf ended up being one of the dependencies I had to upgrade, from thymeleaf2 to thymeleaf3.
Right now, a lot of old thymeleaf templates are completely broken (granted, quite a bit of them were poorly done in the first place), but right now I’m having an issue I’m being completely unable to clear.
<th th:each="opScheduleMap, opIter : ${sessionDTO.opAttendanceSchedule.scheduleMap}">
<div th:if="${opIter.size==1}">
<div id="mapOnlyContainGenericSchedule" style="font-weight: bold;"
th:text="#{'operator.schedule.'+${opScheduleMap.key.getAcronym()}}"></div>
<th th:each="opHours, iter : ${opScheduleMap.value.scheduleHours}">
<span th:text="${opHours.startHour} + #{operator.info.available.time.separator.h}+
' '+ #{operator.info.available.time.separator.en.dash}+' '+ ${opHours.finishHour} +
#{operator.info.available.time.separator.h}+' '">das 00h às 00h</span>
<span th:if="${iter.index < (iter.size - 1)}"
th:text="#{operator.info.available.time.separator.and}+' '"> e </span>
</th>
</div>
</th>
Thymeleaf (or SpEL) decides that sessionDTO.opAttendanceSchedule.scheduleMap has values, but opScheduleMap.value is a null, therefore opScheduleMap.Value.ScheduleHours throws an error.
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'scheduleHours' cannot be found on null
Meanwhile, I can use java to check the values of sessionDTO which is passed onto thymeleaf through spring-webflow, and sessionDTO does have a opAttendanceSchedule, opAttendanceSchedule does have scheduleMaps, which do have values etc.
So I can’t see why thymeleaf (or SpEL) isn’t being able to actually find the values it’s supposed to.
servlet context:
<!-- ************************************************************************ -->
<!-- THYMELEAF-SPECIFIC ARTIFACTS -->
<!-- TemplateResolver <- TemplateEngine <- ViewResolver <- ViewFactoryCreator -->
<!-- ************************************************************************ -->
<bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/"/>
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML"/>
<!-- Template cache is true by default. Set to false if you want -->
<!-- templates to be automatically updated when modified. -->
<property name="cacheable" value="true"/>
<!--<property name="characterEncoding" value="UTF-8"/>-->
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver"/>
<property name="additionalDialects">
<set>
<bean class="org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect"/>
</set>
</property>
</bean>
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring5.webflow.view.AjaxThymeleafViewResolver">
<property name="viewClass" value="org.thymeleaf.spring5.webflow.view.FlowAjaxThymeleafView"/>
<property name="templateEngine" ref="templateEngine"/>
<property name="characterEncoding" value="UTF-8"/>
</bean>
<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="thymeleafViewResolver"/>
</bean>