I am trying to use tiles along with Struts 2. I am using annotations on action classes as shown below. I have defined a default parent package using the Convention Plugin and also defined the package rcg.console
which extends from struts-default
and tiles-default
packages.
However, when I start my Tomcat server, I get the following exception. But, if I change the
@ParentPackage(value="rcg.console")
annotation on my action class to
@ParentPackage(value="tiles-default")
,
the error goes away. If I don't define the @ParentPackage
annotation, struts is not able to detect my "tiles"
result-type
. Can anyone please help me with this?
SEVERE: Exception starting filter struts2
Unable to load configuration. - [unknown location]
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:501)
at org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:74)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.init(StrutsPrepareAndExecuteFilter.java:57)
at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:281)
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:262)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:107)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4656)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5312)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: Unable to load configuration. - [unknown location]
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:70)
at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:445)
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:489)
... 14 more
Caused by: Unable to locate parent package [rcg.console] for [class com.tumri.rcg.actions.ConsoleAction] - [unknown location]
at org.apache.struts2.convention.PackageBasedActionConfigBuilder.getPackageConfig(PackageBasedActionConfigBuilder.java:1020)
at org.apache.struts2.convention.PackageBasedActionConfigBuilder.buildConfiguration(PackageBasedActionConfigBuilder.java:666)
at org.apache.struts2.convention.PackageBasedActionConfigBuilder.buildActionConfigs(PackageBasedActionConfigBuilder.java:348)
at org.apache.struts2.convention.ClasspathPackageProvider.loadPackages(ClasspathPackageProvider.java:53)
at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:268)
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:67)
... 16 more
My struts.xml
file:
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd ">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />
<constant name="struts.convention.default.parent.package" value="rcg.console"/>
<constant name="struts.custom.i18n.resources" value="messages" />
<package name="rcg.console" extends="struts-default, tiles-default" namespace="/"></package>
</struts>
My web.xml
file:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>rcg-webapp</display-name>
<context-param>
<param-name>org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG</param-name>
<param-value>/WEB-INF/tiles.xml</param-value>
</context-param>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.apache.struts2.tiles.StrutsTilesListener
</listener-class>
</listener>
</web-app>
My tiles.xml
file:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
<definition name="rcg.defaultLayout"
template="/layouts/default/defaultLayout.jsp">
<put-attribute name="title" value="RCG Console" />
<put-attribute name="header" value="/layouts/default/header.jsp" />
<!-- <put-attribute name="tabs" value="/layouts/default/tabs.jsp" /> -->
<put-attribute name="body" value="" />
<put-attribute name="footer" value="/layouts/default/footer.jsp" />
</definition>
<definition name="rcg.consoleHome" extends="rcg.defaultLayout">
<put-attribute name="body" value="/jsp/consoleHome.jsp" />
</definition >
</tiles-definitions>
My Action class:
package com.tumri.rcg.actions;
import org.apache.log4j.Logger;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import com.opensymphony.xwork2.ActionSupport;
@Namespace(value="/")
@ParentPackage(value="rcg.console")
@Results(value={@Result(name="success", type="tiles", location ="rcg.consoleHome")})
@Actions(value={@Action(""), @Action("console")})
public class ConsoleAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 4622874962298947031L;
Logger logger = Logger.getLogger(ConsoleAction.class);
@Override
public String execute() throws Exception {
System.out.println("Executing Index Action...");
logger.info("Executing Index Action...");
return SUCCESS;
}
}
To use
@ParentPackage
annotation with the action class or Java package you have to specify the valid Struts package name as a value attribute. If Struts is unable to find the specified package name it will inform you with the exception like in your caseThis is normal, the specified Struts package must exist in the Struts runtime configuration before the convention plugin configuration provider would create its own configuration based on conventions.
If you change the Struts package name to a package like
tiles-default
orconvention-default
it will work, because these Struts packages are created via the XML-based configuration provider from the plugin configuration files.But, your package is not created, because you didn't supply the configuration file
struts.xml
to your web application or it's not accessible by the dispatcher. By defaultstruts.xml
is placed on classpath where it could be loaded by the context classloader or you can specify the location of the configuration file usingconfig
init parameter of the Struts filter.Default result types are available to the parent packages which your packages should extend.