Thymeleaf SpEL null on object that is not supposed to be null

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.

Debug evaluation of sessionDTO.getOpAttendanceSchedule().getScheduleMap()

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>

Leave a Comment