[
https://issues.apache.org/jira/browse/TILES-513?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12903507#action_12903507
]
Jamie Goodfellow commented on TILES-513:
----------------------------------------
Great, thanks! I didn't want to submit a patch because I don't know the full
mechanics of the various objects well enough to not break something else..
> Simultaneous definition requests to multiple locales causes
> NoSuchDefinitionException on anonymousDefinition
> ------------------------------------------------------------------------------------------------------------
>
> Key: TILES-513
> URL: https://issues.apache.org/jira/browse/TILES-513
> Project: Tiles
> Issue Type: Bug
> Components: tiles-core
> Affects Versions: 2.1.4, 2.2.2
> Reporter: Jamie Goodfellow
> Assignee: Antonio Petrelli
>
> When simultaneously loading the same tiles definition for two locales (in my
> case, en_CA and es_CO) and a third empty locale, they empty locale request
> results in a stack trace claiming an anonymous definition could not be found.
> I traced this to a synchronization issue in CachingLocaleUrlDefinitionDAO
> and ResolvingLocaleUrlDefinitionDAO. The issue seems to be that the
> loadParentDefinitions method loads the parent locale definitions into the
> locale2definitionMap map regardless if the map already contains an entry for
> the requested locale. Alone this is fine, since the update is synchronized
> in a previous method call in the stack trace. However when the three
> requests come in simultaneously, and the requested definition has nested
> anonymous definitions, there is a timing issue.
> The first request (say en_CA) requests the root definition (in this case
> 'security/login'). This causes the root, en, and en_CA definition maps to be
> loaded. At the same time, the second request (es_CO) requests the
> 'security/login' definition. This will cause the root, es, and es_CO
> definitions to be loaded (overwriting the root locale with new anonymous
> definitions). The third request (empty locale) will request the
> 'security/login' definition as well. The definition processing will then see
> that the security/login definition references other definitions, and begin
> requesting anonymous definitions. However, since the root locale has been
> overwritten, the requested definitions no longer appear in the root map.
> This results in the stack trace below.
> Appended below are my tiles definition configurations and the stack trace,
> for reference. I've also applied a fix for myself. In Tiles 2.2.2, I
> updated the loadParentDefinitions in ResolvingLocaleUrlDefinitionDAO to check
> if the map already contains an entry for the requested locale, and returns
> the existing entry if so:
> @Override
> protected Map<String, Definition> loadParentDefinitions(Locale
> parentLocale) {
> if(locale2definitionMap.containsKey(parentLocale)) {
> return
> copyDefinitionMap(locale2definitionMap.get(parentLocale));
> } else {
> return loadDefinitionsFromURLs(parentLocale);
> }
> }
> I've verified this fixes my issue.
> <!-- Authentication Layout -->
> <definition name="authLayout" template="/WEB-INF/layouts/auth.jsp">
> <put-attribute name="header">
> <definition template="/WEB-INF/layouts/auth/header.jsp"
> />
> </put-attribute>
> <put-attribute name="localnav">
> <definition
> template="/WEB-INF/layouts/auth/localnav.jsp" />
> </put-attribute>
> <put-attribute name="footer">
> <definition template="/WEB-INF/layouts/auth/footer.jsp"
> />
> </put-attribute>
> </definition>
> <!-- index page -->
> <definition name="security/login" extends="authLayout">
> <put-attribute name="title" value="page.title.security.login" />
> <put-attribute name="navTab" value="security" />
> <put-attribute name="main"
> value="/WEB-INF/views/security/login.jsp" />
> </definition>
> org.apache.tiles.definition.NoSuchDefinitionException: $anonymousDefinition7
>
> org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:625)
>
> org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:321)
>
> org.apache.tiles.renderer.impl.DefinitionAttributeRenderer.write(DefinitionAttributeRenderer.java:56)
>
> org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
>
> org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
>
> org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:336)
>
> org.apache.tiles.template.InsertAttributeModel.renderAttribute(InsertAttributeModel.java:210)
>
> org.apache.tiles.template.InsertAttributeModel.end(InsertAttributeModel.java:126)
>
> org.apache.tiles.jsp.taglib.InsertAttributeTag.doTag(InsertAttributeTag.java:311)
>
> org.apache.jsp.WEB_002dINF.layouts.auth_jsp._jspx_meth_tiles_005finsertAttribute_005f0(auth_jsp.java:899)
>
> org.apache.jsp.WEB_002dINF.layouts.auth_jsp._jspService(auth_jsp.java:228)
> org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
> javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
>
> org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
> org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
> org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
> javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
>
> org.apache.tiles.servlet.context.ServletTilesRequestContext.forward(ServletTilesRequestContext.java:241)
>
> org.apache.tiles.servlet.context.ServletTilesRequestContext.dispatch(ServletTilesRequestContext.java:222)
>
> org.apache.tiles.renderer.impl.TemplateAttributeRenderer.write(TemplateAttributeRenderer.java:44)
>
> org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
>
> org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
>
> org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:690)
>
> org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:644)
>
> org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:627)
>
> org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:321)
>
> org.springframework.web.servlet.view.tiles2.TilesView.renderMergedOutputModel(TilesView.java:124)
>
> org.springframework.js.ajax.tiles2.AjaxTilesView.renderMergedOutputModel(AjaxTilesView.java:115)
>
> org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250)
>
> org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1063)
>
> org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:801)
>
> org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
>
> org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
>
> org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
> javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
> javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
>
> com.truecontext.prontoforms.pes.aspect.audit.impl.filter.AuditContextSettingFilter.doFilterInternal(AuditContextSettingFilter.java:50)
>
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
>
> org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
>
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
>
> org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:113)
>
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
>
> com.truecontext.prontoforms.pes.web.filter.IncompleteUserFilter.doFilterInternal(IncompleteUserFilter.java:50)
>
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
>
> org.springframework.web.filter.AbstractRequestLoggingFilter.doFilterInternal(AbstractRequestLoggingFilter.java:193)
>
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:343)
>
> org.springframework.security.web.authentication.switchuser.SwitchUserFilter.doFilter(SwitchUserFilter.java:177)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
>
> org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
>
> org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
>
> org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
>
> org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
>
> org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
>
> org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:112)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
>
> org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
>
> org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
>
> com.truecontext.common.web.aspects.security.authentication.www.UrlSpecificBasicAuthenticationFilter.doFilter(UrlSpecificBasicAuthenticationFilter.java:105)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
>
> org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
>
> org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
>
> org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
>
> org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
>
> org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
>
> org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
>
> org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
>
> org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
>
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
>
> org.springframework.web.filter.ShallowEtagHeaderFilter.doFilterInternal(ShallowEtagHeaderFilter.java:57)
>
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.