Why Tiles REGEXP wildcard definition cause endless jsp including error
I use tiles 2.2.2 with Struts2 2.2.3, since Struts2-Tiles plugin is quite old, its implementation uses many Tiles deprecated API, and I want to try REGEXP wildcard, so I implement my own listener below:
MyTilesContainerFactory
package tiles;
import org.apache.tiles.definition.pattern.DefinitionPatternMatcherFactory;
import org.apache.tiles.definition.pattern.PatternDefinitionResolver;
import org.apache.tiles.definition.pattern.PrefixedPatternDefinitionResolver;
import org.apache.tiles.definition.pattern.regexp.RegexpDefinitionPatternMatcherFactory;
import org.apache.tiles.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory;
import org.apache.tiles.factory.BasicTilesContainerFactory;
public class MyTilesContainerFactory extends BasicTilesContainerFactory {
@Override
protected <T> PatternDefinitionResolver<T> createPatternDefinitionResolver(Class<T> customizationKeyClass) {
DefinitionPatternMatcherFactory wildcardFactory = new WildcardDefinitionPatternMatcherFactory();
DefinitionPatternMatcherFactory regexpFactory = new RegexpDefinitionPatternMatcherFactory();
PrefixedPatternDefinitionResolver<T> resolver = new PrefixedPatternDefinitionResolver<T>();
resolver.registerDefinitionPatternMatcherFactory("WILDCARD", wildcardFactory);
resolver.registerDefinitionPatternMatcherFactory("REGEXP", regexpFactory);
return resolver;
}
}
MyTilesInitializer
package tiles;
import org.apache.tiles.TilesApplicationContext;
import org.apache.tiles.factory.AbstractTilesContainerFactory;
import org.apache.tiles.startup.AbstractTilesInitializer;
public class MyTilesInitializer extends AbstractTilesInitializer {
@Override
protected AbstractTilesContainerFactory createContainerFactory(TilesApplicationContext context) {
return new MyTilesContainerFactory();
}
}
MyTilesListener
package tiles;
import org.apache.tiles.startup.TilesInitializer;
import org.apache.tiles.web.startup.AbstractTilesListener;
public class MyTilesListener extends AbstractTilesListener {
@Override
protected TilesInitializer createTilesInitializer() {
return new MyTilesInitializer();
}
}
Then I define my tiles.xml
<tiles-definitions>
<definition name="REGEXP:(.*)" template="/WEB-INF/tiles/basicLayout.jsp">
<put-attribute name="header" value="/WEB-INF/tiles/header.jsp" />
<put-attribute name="content" value="/WEB-INF/pages/{1}.jsp" />
<put-attribute name="footer" value="/WEB-INF/tiles/footer.jsp" />
</definition>
</tiles-definitions>
When I try a action that returns a tiles result, it ends up with an infinite loop, a jsp include error.
SEVERE: Servlet.service() for servlet jsp threw exception
java.lang.StackOverflowError
at java.io.UnixFileSystem.getBooleanAttributes0(Native Method)
at java.io.UnixFileSystem.getBooleanAttributes(UnixFileSystem.java:228)
at java.io.File.exists(File.java:733)
at sun.misc.URLClassPath$FileLoader.getResource(URLClassPath.java:999)
at sun.misc.URLClassPath.getResource(URLClassPath.java:169)
at java.net.URLClassLoader$1.run(URLClassLoader.java:194)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at org.apache.jasper.compiler.ErrorDispatcher.createJavacError(ErrorDispatcher.java:526)
at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:490)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:416)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:337)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:630)
at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:535)
at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:472)
at org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:968)
at org.apache.jasper.runtime.PageContextImpl.doInclude(PageContextImpl.java:638)
at org.apache.jasper.runtime.PageContextImpl.include(PageContextImpl.java:632)
at org.apache.tiles.jsp.context.JspTilesRequestContext.include(JspTilesRequestContext.java:103)
at org.apache.tiles.jsp.context.JspTilesRequestContext.dispatch(JspTilesRequestContext.java:96)
at org.apache.tiles.renderer.impl.TemplateAttributeRenderer.write(TemplateAttributeRenderer.java:44)
at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:690)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:644)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:627)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:321)
at org.apache.tiles.renderer.impl.DefinitionAttributeRenderer.write(DefinitionAttributeRenderer.java:56)
at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
at org.apache.tiles.renderer.impl.ChainedDelegateAttributeRenderer.write(ChainedDelegateAttributeRenderer.java:76)
at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:336)
at org.apache.tiles.template.InsertAttributeModel.renderAttribute(InsertAttributeModel.java:210)
at org.apache.tiles.template.InsertAttributeModel.end(InsertAttributeModel.java:126)
at org.apache.tiles.jsp.taglib.InsertAttributeTag.doTag(InsertAttributeTag.java:311)
at org.apache.jsp.WEB_002dINF.tiles.basicLayout_jsp._jspx_meth_tiles_005finsertAttribute_005f0(basicLayout_jsp.java:128)
at org.apache.jsp.WEB_002dINF.tiles.basicLayout_jsp._jspService(basicLayout_jsp.java:93)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:337)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:630)
at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:535)
at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:472)
at org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:968)
at org.apache.jasper.runtime.PageContextImpl.doInclude(PageContextImpl.java:638)
at org.apache.jasper.runtime.PageContextImpl.include(PageContextImpl.java:632)
at org.apache.tiles.jsp.context.JspTilesRequestContext.include(JspTilesRequestContext.java:103)
at org.apache.tiles.jsp.context.JspTilesRequestContext.dispatch(JspTilesRequestContext.java:96)
at org.apache.tiles.renderer.impl.TemplateAttributeRenderer.write(TemplateAttributeRenderer.java:44)
at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:690)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:644)
at org.apache.tiles.impl.BasicTilesContainer开发者_StackOverflow社区.render(BasicTilesContainer.java:627)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:321)
at org.apache.tiles.renderer.impl.DefinitionAttributeRenderer.write(DefinitionAttributeRenderer.java:56)
at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
at org.apache.tiles.renderer.impl.ChainedDelegateAttributeRenderer.write(ChainedDelegateAttributeRenderer.java:76)
at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:106)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:670)
at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:336)
at org.apache.tiles.template.InsertAttributeModel.renderAttribute(InsertAttributeModel.java:210)
at org.apache.tiles.template.InsertAttributeModel.end(InsertAttributeModel.java:126)
at org.apache.tiles.jsp.taglib.InsertAttributeTag.doTag(InsertAttributeTag.java:311)
at org.apache.jsp.WEB_002dINF.tiles.basicLayout_jsp._jspx_meth_tiles_005finsertAttribute_005f0(basicLayout_jsp.java:128)
at org.apache.jsp.WEB_002dINF.tiles.basicLayout_jsp._jspService(basicLayout_jsp.java:93)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
Could any one give me advice? I have to say that if I didn't use wildcard definition, the same definition works fine. Thanks a lot.
I haven't quite worked this out to my satisfaction but I hope it helps. The regular expression you are using is probably the greediest expression you could possibly use. It matches everything and this includes everything inside the tiles definition itself (basicLayout.jsp, header.jsp, footer.jsp). This explains why you are getting an infinite loop as your REGEXP tiles definition keeps matching every file request and attempting to satisfy each new file request with a new template invocation (template recursion!).
The Tiles Wildcard support page shows several examples. None of these examples use (.*) - I think we have just worked out why this might be.
You will need to make your REGEXP slightly less greedy; I know Struts uses a slightly different approach to invoke template tiles but imagine you have a JSP page containing:
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<tiles:insertDefinition name="somepage.tile" />
and the following tiles definition should create your template page wrapped around the content from /WEB-INF/pages/somepage.jsp:
<definition name="REGEXP:(.*)\.tile" template="/WEB-INF/tiles/basicLayout.jsp">
<put-attribute name="header" value="/WEB-INF/tiles/header.jsp" />
<put-attribute name="content" value="/WEB-INF/pages/{1}.jsp" />
<put-attribute name="footer" value="/WEB-INF/tiles/footer.jsp" />
</definition>
精彩评论