Strange behavior in thymeleaf - need HELP

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Strange behavior in thymeleaf - need HELP

niels
Yesterday I get a behavior which let me doubt that thymeleaf is production ready. Here my constellation:

I have 3 entities user, post and tag. For all of them I have a simple CRUD-Controller which uses a list.html and a form.html. Furthermore I have a templates.html where I defined some layout:fragment and th:fragments.

The error happens in templates.html. I get
    Exception evaluating SpringEL expression: "class.name" (templates:39)

Caused by:

org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "class.name" (templates:39)
....
Caused by: org.springframework.expression.AccessException: Unable to access property 'name' through getter
....
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
Line 39 in templates.html is
            th:text="#{__*{class.name}__.__${fId}__}+':'">
In form.html I have define a form an the fId. I want to get the class-name of the object. This works pretty well for user and post. Then I copied my files for tag and the trouble starts.
If I restart Jetty and reload the page everything is fine. If I go back to the list I get a similar error. Again restart jetty  and reload fix the bug. Seems for me an caching issue. This is a strange because I have defined resolver.setCacheable(false);. Furthermore it only seems a problem for the entity tag. I tried to rename the class to MyTag and the model-name from tag to mytag, but this doesn't help.

I'm writing at the moment for a talk, where some parts based on thymeleaf. So any hint are really appreciated.
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

Zemi
Administrator
Without analising deep the problem, have you tried replacing
    *{class.name}
for
    ${yourBean.class.name}
where 'yourBean' is the same you have inside the th:object attribute.

Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

niels
The problem is that I'm in a fragment. So I don't know the name of the bean. I only know I'm in a form where a bean must defined.
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

Zemi
Administrator
Again, without entering to the cause of the problem (which I don't know), maybe you could pass the bean to the include using th:with
    <div th:with="formBean=${myBean}" th:include="templates.html::whatever" />
and use it inside
    th:text="#{__${formBean.class.name}__.__${fId}__}+':'">
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

danielfernandez
Administrator
In reply to this post by niels
niels wrote
[...] Seems for me an caching issue. This is a strange because I have defined resolver.setCacheable(false);. Furthermore it only seems a problem for the entity tag.
Actually, caching does not affect expression evaluation. DOM nodes, their attributes and the processors that should be applied to them are cached, but never expression results. Expressions are always executed each time a template is executed.

Could it be your "tag" object is null sometimes? Are you using a standard "th:fragment" there or a layout-dialect "layout:fragment"?

From the data you give I'm not able to identify your problem. I've tested the following scenario:

frags.html file:

<div th:fragment="f1">

   <p>
      Some text here
   </p>   
   <div th:text="#{__*{class.name}__.__${fId}__}+':'">lalero</div>
   <p>   
      Some more text here
   </p>
</div>

Then three files like this, each one selecting a different object at its "th:object" (user, post and tag):

<!DOCTYPE html>

<html lang="en">

<head>
   <title>one</title>
</head>

<body th:with="fId=23">

   <p>Some text from the outer page here</p>

   <form th:object="${user}">
      <div th:include="fragments/frags :: f1">lululu</div>
   </form>
   <p>Some text from the outer page here</p>

</body>

</html>

The "user", "post" and "tag" objects are of completely different classes. They are initialized at the controller and added to the model so that they are available for these pages.

None of these give any errors using thymeleaf 2.0.16 and Spring 3.2.2 on Tomcat 7.

If you "tag" object is never null... could this be an issue with your jetty server?

Regards,
Daniel.
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

niels
In reply to this post by Zemi
I tried the trick with formBean=${tag} and use in the fragment ${tag} /with the last one the fragment is useless, but just for test. Both doesn't really help. How ever it seems that it now more difficult to reproduce.
Niels
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

niels
I think I must correct my last statement  formBean=${tag} seams to work. I call it at the form tag.
<form th:action="@{${url}}" class="well form-horizontal" method="post" th:object="${tag}"  th:with="formBean=${tag}">
Not very elegant but it seems to work, at least at the moment.
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

niels
In reply to this post by danielfernandez
@Daniel: I used both th:fragment and layout:fragment. The error happens in th:fragment. I checked the tag value at the moment I put it into the map. So in the map it's definitely not null.
Can't see how Jetty could have influence on it.
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP


so here I don't use the *{ syntax. tag can't be null because in line 48 I asked for the id.

Interesting it's always a problem with name!


niels
Some additional information - perhaps it helps

I restartet jetty and opened the edit-page with use form.html and the template.html. This works fine. Than I go to the list.html and get a similar error. First a snippet from list.html:
<body>
    <h3 th:text="#{tag.list.title}">List of tags</h3>
    <a class="btn" href="/" th:href="@{/}"><i class="icon-home"></i>Home</a>
    <a class="btn" href="/" th:href="@{__#{url.tag.create}__}" th:text="#{label.action.create}">Create a new tag</a>
    <div id="data">
        <span th:if="${#lists.isEmpty(tagList)}" th:text="#{label.no_data_found}"></span>
        <table class="table table-striped table-hover">
            <thead>
                <tr>
                    <th>Id</th>
                    <th th:text="#{de.ppi.samples.springmvc.model.Tag.name}">Name</th>
                    <th th:text="#{de.ppi.samples.springmvc.model.Tag.active}">Active</th>
                    <th th:text="#{label.actions}">Actions</th>
                </tr>
            </thead>

            <tbody>
                <tr th:each="tag : ${tagList.content}">
                    <td th:text="${tag.id}">1</td>
                    <td th:text="${tag.name}">Test</td>
                    <td th:text="${tag.active}">J</td>
                    <td><a class="btn" href="show/1" th:href="@{__#{url.tag.show(${tag.id})}__}" th:text="#{label.action.show}">Show</a>
                        <a class="btn" href="edit/1" th:href="@{__#{url.tag.edit(${tag.id})}__}" th:text="#{label.action.edit}">Update</a>
                        <a class="btn" href="delete/1" th:href="@{__#{url.tag.delete(${tag.id})}__}" th:text="#{label.action.delete}">Delete</a>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>


Here the error:
Exception evaluating SpringEL expression: "tag.name" (tag/list:49)

org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "tag.name" (tag/list:49)
	at org.thymeleaf.spring3.expression.SpelVariableExpressionEvaluator.evaluate(SpelVariableExpressionEvaluator.java:108)
	at org.thymeleaf.standard.expression.VariableExpression.executeVariable(VariableExpression.java:116)
	at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:394)
	at org.thymeleaf.standard.expression.Expression.execute(Expression.java:231)
	at org.thymeleaf.standard.expression.StandardExpressionExecutor.executeExpression(StandardExpressionExecutor.java:70)
	at org.thymeleaf.standard.expression.StandardExpressionExecutor.executeExpression(StandardExpressionExecutor.java:58)
	at org.thymeleaf.standard.expression.StandardExpressionProcessor.executeExpression(StandardExpressionProcessor.java:124)
	at org.thymeleaf.standard.expression.StandardExpressionProcessor.processExpression(StandardExpressionProcessor.java:164)
	at org.thymeleaf.standard.processor.attr.AbstractStandardTextChildModifierAttrProcessor.getText(AbstractStandardTextChildModifierAttrProcessor.java:60)

....
Caused by: org.springframework.expression.AccessException: Unable to access property 'name' through getter
	at org.springframework.expression.spel.support.ReflectivePropertyAccessor$OptimalPropertyAccessor.read(ReflectivePropertyAccessor.java:571)
	at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:234)
	... 72 more
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class

The line 49 is
       
Test
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

danielfernandez
Administrator
In reply to this post by niels
From what I can read, this error and its nested one:

Caused by: org.springframework.expression.AccessException: Unable to access property 'name' through getter
...
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class

Seems to be raised at line 154 of Spring EL's ReflectivePropertyAccessor in Spring 3.2.1:
http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring-expression/3.2.1.RELEASE/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java?av=f#154

And the reason to have an "object is not an instance of declaring class" is that we have obtained a Method or Field instance during reflection that we afterwards try to use on a target object that is not of the originating class of such Method/Field instance.

Given should be accessing the "name" property of a java.lang.Class object, this is quite weird, as such getter should always exist.

IMHO this doesn't seem thymeleaf related at all, as expression evaluation is the entire responsibility of the SpringEL engine. Could be a bug, maybe a SecurityManager issue... don't know. What version of Spring are you using?

Regards
Daniel

Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

niels
Well I used 3.2.2 the exception raised in at org.springframework.expression.spel.support.ReflectivePropertyAccessor$OptimalPropertyAccessor.read(ReflectivePropertyAccessor.java:567)
if you look into the code, you can see that first the method will be defined and later it will be called. So if someone stores the OptimalPropertyAccessor in a wrong way it could makes the trouble. You analyze class which has a name but ask for name for String which doesn't has getName().
I will try to track it more down to make it more clear where the problem is.

Niels
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

niels
If I rename the column name in the class Tag to tagname everything is fine. So the problem seems to be the column-name "name". I'm only wondering while ${beanName.class.name} seems to help, while *{class.name} makes the trouble.
Any hint hwo to track this more down is appreciate.
Niels
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

niels
Can now reproduce the error even with ${beanName.class.name}. So it looks more and more like a bug in Spring to me :-/
Makes it sense to make it reproducible with the stsm-example app.
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

niels
Added a name attribute to the seedstarter sample. Now I can reproduce it there. How can I send you the code?
I added an attribute name and a method to the controller to show my new form. Here the template, which shows that it's not a problem of fragments. The spring version doesn't seems the problem.

<!DOCTYPE HTML>
<html lang="de-DE" xmlns:th="http://www.thymeleaf.org"
    xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout">
<head>
<meta charset="UTF-8" />
</head>
<body>
    <form th:action="@{${url}}" class="well form-horizontal" method="post" th:object="${tag}">
        <div class="control-group" th:with="fId='name'"
            th:classappend="${#fields.hasErrors('__${fId}__')}? 'error'">
            <label class="control-label" th:for="${fId}"
                th:text="#{__*{class.name}__.__${fId}__}+':'">
            FirstName </label>
            <div class="controls">
                <input type="text" th:class="${inputclass}" th:field="*{__${fId}__}" th:disabled="${disabled}"/>
                <span class="help-inline" th:if="${#fields.hasErrors('__${fId}__')}"
                    th:errors="*{__${fId}__}"></span>
            </div>
          </div>

        <input name="" value="Save" type="submit" th:if="${not disabled}"/>
        <input name="" value="Reset" type="reset" th:if="${not disabled}"/>
    </form>
</body>
</html>

 
So I hope it's enough information. Would be really great to get some feedback, do know what are the next steps.
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

danielfernandez
Administrator

If you have a GitHub user, you can do a pull request on thymeleaf/thymeleafexamples-stsm which I can convert into a new branch for testing.

If not, just send me an email. My address is at the Thymeleaf team page.

El 24/04/2013 16:32, "niels [via Thymeleaf - User Forum]" <[hidden email]> escribió:
Added a name attribute to the seedstarter sample. Now I can reproduce it there. How can I send you the code?
I added an attribute name and a method to the controller to show my new form. Here the template, which shows that it's not a problem of fragments. The spring version doesn't seems the problem.

<!DOCTYPE HTML>
<html lang="de-DE" xmlns:th="http://www.thymeleaf.org"
    xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout">
<head>
<meta charset="UTF-8" />
</head>
<body>
    <form th:action="@{${url}}" class="well form-horizontal" method="post" th:object="${tag}">
        <div class="control-group" th:with="fId='name'"
            th:classappend="${#fields.hasErrors('__${fId}__')}? 'error'">
            <label class="control-label" th:for="${fId}"
                th:text="#{__*{class.name}__.__${fId}__}+':'">
            FirstName </label>
            <div class="controls">
                <input type="text" th:class="${inputclass}" th:field="*{__${fId}__}" th:disabled="${disabled}"/>
                <span class="help-inline" th:if="${#fields.hasErrors('__${fId}__')}"
                    th:errors="*{__${fId}__}"></span>
            </div>
          </div>

        <input name="" value="Save" type="submit" th:if="${not disabled}"/>
        <input name="" value="Reset" type="reset" th:if="${not disabled}"/>
    </form>
</body>
</html>

 
So I hope it's enough information. Would be really great to get some feedback, do know what are the next steps.


If you reply to this email, your message will be added to the discussion below:
http://forum.thymeleaf.org/Strange-behavior-in-thymeleaf-need-HELP-tp4025949p4025962.html
To start a new topic under General Usage, email [hidden email]
To unsubscribe from General Usage, click here.
NAML
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

danielfernandez
Administrator
In reply to this post by niels
Hi niels,

I've tested your code. The "${not disabled}" expression in the input fields at the end of your page raise an error because "disabled" is null, but except for that, your test page works OK for me in Spring 3.2 and raises a SpringEL exception for "class.name" in Spring 3.0 and Spring 3.1.

I've created this gist: https://gist.github.com/danielfernandez/5456537 with no thymeleaf at all, which you can use to check this behaviour.

It seems therefore to be a Spring issue, solved in Spring 3.2. Not thymeleaf related.

Regards,
Daniel.

Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

danielfernandez
Administrator
Found it. Here it is: https://jira.springsource.org/browse/SPR-9017

Regards,
Daniel
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior in thymeleaf - need HELP

niels
Thanks for showing that it's a spring-problem. I fork your GIST and created a version which shows my problem. It's unfortunately not fixed in 3.2.2.
https://gist.github.com/opensource21/5457631 shows the bug.

I created an bug report at SpringSource https://jira.springsource.org/browse/SPR-10486.

Perhaps a ${#objects.getClassName(obj)} is a good idea? Another option for me could be ${#strings.substringAfter(#strings.toString(*{class}),"Class ")}

Thanks for your support
Niels