SpelParseException -- how to debug?

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

SpelParseException -- how to debug?

benr

I am trying out Thymeleaf and in general I find it to be very good, however I have come across an error message on parsing a template of mine that I have no idea how to fix.

The error is:

org.springframework.expression.spel.SpelParseException: EL1043E:(pos 20): Unexpected token. Expected 'rparen())' but was 'lcurly({)'

I've scanned through the content of my template(s) multiple times, but no left curly bracket seems out of place. How do I enable debugging or logging to find out which line of which file is causing the problem?

Cheers,
Ben

Reply | Threaded
Open this post in threaded view
|

Re: SpelParseException -- how to debug?

Emanuel
Administrator
I've found that Thymeleaf usually prints out which line the error appears on somewhere on the stacktrace (not always the first exception that's printed, but it's in there somewhere), so if you were able to find the SpelParseException, then I'd suspect the Thymeleaf error should be around there too (same log file?).

Otherwise, Thymeleaf uses SLF4J for its logging which just redirects to a logging implementation.  Depending on your choice of logger, I think you'll need to specify DEBUG level logging for the org.thymeleaf logger.

If you're using Logback as the logging implementation, then it might look something like this in your logback.xml configuration file:

<logger name="org.thymeleaf" level="debug">
  <appender-ref ref="console"/>
</logger>

Where 'console' is the name of an appender configured elsewhere in your file.
Reply | Threaded
Open this post in threaded view
|

Re: SpelParseException -- how to debug?

benr
Emanuel wrote

I've found that Thymeleaf usually prints out which line the error appears on somewhere on the stacktrace (not always the first exception that's printed, but it's in there somewhere), so if you were able to find the SpelParseException, then I'd suspect the Thymeleaf error should be around there too (same log file?).

That's what I had done, but there is no line number output. Tracking back from Spring Framework code, org.thymeleaf.processor.AbstractProcessor.process(AbstractProcessor.java:212) is the first place within Thymeleaf where I can find a try/catch block. I don't get why this wouldn't catch the underlying exception, but I guess Spring Framework handles it rather than throwing it.

org.springframework.expression.spel.SpelParseException: EL1043E:(pos 20): Unexpected token.  Expected 'rparen())' but was 'lcurly({)'
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.raiseInternalException(InternalSpelExpressionParser.java:814)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatToken(InternalSpelExpressionParser.java:744)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.maybeEatMethodArgs(InternalSpelExpressionParser.java:391)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.maybeEatMethodOrProperty(InternalSpelExpressionParser.java:604)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatDottedNode(InternalSpelExpressionParser.java:350)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.maybeEatNode(InternalSpelExpressionParser.java:316)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatPrimaryExpression(InternalSpelExpressionParser.java:302)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatUnaryExpression(InternalSpelExpressionParser.java:293)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatUnaryExpression(InternalSpelExpressionParser.java:283)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatPowerExpression(InternalSpelExpressionParser.java:269)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatProductExpression(InternalSpelExpressionParser.java:250)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatSumExpression(InternalSpelExpressionParser.java:233)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatRelationalExpression(InternalSpelExpressionParser.java:195)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatLogicalAndExpression(InternalSpelExpressionParser.java:183)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatLogicalOrExpression(InternalSpelExpressionParser.java:171)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatExpression(InternalSpelExpressionParser.java:135)
	at org.springframework.expression.spel.standard.InternalSpelExpressionParser.doParseExpression(InternalSpelExpressionParser.java:116)
	at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:56)
	at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:1)
	at org.springframework.expression.common.TemplateAwareExpressionParser.parseExpression(TemplateAwareExpressionParser.java:66)
	at org.springframework.expression.common.TemplateAwareExpressionParser.parseExpression(TemplateAwareExpressionParser.java:56)
	at org.thymeleaf.spring3.expression.SpelExpressionEvaluator.getExpression(SpelExpressionEvaluator.java:129)
	at org.thymeleaf.spring3.expression.SpelExpressionEvaluator.evaluate(SpelExpressionEvaluator.java:101)
	at org.thymeleaf.standard.expression.VariableExpression.executeVariable(VariableExpression.java:116)
	at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:392)
	at org.thymeleaf.standard.expression.Expression.execute(Expression.java:228)
	at org.thymeleaf.standard.expression.StandardExpressionExecutor.executeExpression(StandardExpressionExecutor.java:58)
	at org.thymeleaf.standard.expression.StandardExpressionProcessor.executeExpression(StandardExpressionProcessor.java:84)
	at org.thymeleaf.standard.expression.StandardExpressionProcessor.processExpression(StandardExpressionProcessor.java:91)
	at org.thymeleaf.standard.processor.attr.AbstractStandardConditionalVisibilityAttrProcessor.isVisible(AbstractStandardConditionalVisibilityAttrProcessor.java:59)
	at org.thymeleaf.processor.attr.AbstractConditionalVisibilityAttrProcessor.processAttribute(AbstractConditionalVisibilityAttrProcessor.java:58)
	at org.thymeleaf.processor.attr.AbstractAttrProcessor.doProcess(AbstractAttrProcessor.java:74)
	at org.thymeleaf.processor.AbstractProcessor.process(AbstractProcessor.java:212)
	at org.thymeleaf.dom.Node.applyNextProcessor(Node.java:805)
	at org.thymeleaf.dom.Node.processNode(Node.java:767)
	at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:626)
	at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:608)
	at org.thymeleaf.dom.Node.processNode(Node.java:785)
	at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:626)
	at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:608)
	at org.thymeleaf.dom.Node.processNode(Node.java:785)
	at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:626)
	at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:608)
	at org.thymeleaf.dom.Node.processNode(Node.java:785)
	at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:626)
	at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:608)
	at org.thymeleaf.dom.Node.processNode(Node.java:785)
	at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:626)
	at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:608)
	at org.thymeleaf.dom.Node.processNode(Node.java:785)
	at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:626)
	at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:608)
	at org.thymeleaf.dom.Node.processNode(Node.java:785)
	at org.thymeleaf.dom.Document.process(Document.java:90)
	at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1029)
	at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:978)
	at org.thymeleaf.spring3.view.ThymeleafView.render(ThymeleafView.java:460)
	at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1047)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:817)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:574)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:369)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
	at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
	at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:177)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:168)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Thread.java:662)
Reply | Threaded
Open this post in threaded view
|

Re: SpelParseException -- how to debug?

Emanuel
Administrator
Darn, I was afraid that Spring would have caught the exception or just handled it differently.  Any chance we could get a look at the page code causing the error, or a small example that also causes the error?
Reply | Threaded
Open this post in threaded view
|

Re: SpelParseException -- how to debug?

benr

Ah. Just as I was about to cut-n-paste the full template, I found the problem:

th:if="${! #strings.isEmpty(${bean.description})}"

which should be:

th:if="${! #strings.isEmpty(bean.description)}"

I'm still getting my head around SpEL and when I need to wrap something in ${}. Still, it would be nice to catch this misuse of SpEL and Thymeleaf, as it caused me a bit of trouble.