I've created a Struts2 project which is working fine when I place my struts.xml file inside src directory.
Below is my web.xml configuration.
<?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_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>struts2project</display-name>
<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>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
If I put my struts.xml inside WEB-INF directory instead, it is not getting loaded.
Please do not give answers as "it is irrelevant" or something else. I'm just asking whether (and how) we can change the default location of struts.xml or not.
To be completely clear, you don't even need struts.xml, the only needed configuration file is web.xml.
From Configuration Files
From a Struts developer point of view, the one required configuration
file used by the framework is web.xml. From here, you have full
control over how Struts configures both itself and your application.
By default, Struts will load a set of internal configuration files to
configure itself, then another set to configure your application,
however it is possible to build an entire Struts application without
writing a single configuration file other than web.xml.
[...]
File Optional Location (relative to webapp) Purpose
-----------------------------------------------------------------------------------------
web.xml no /WEB-INF/ Web deployment descriptor to include
all necessary framework components
-----------------------------------------------------------------------------------------
struts.xml yes /WEB-INF/classes/ Main configuration, contains
result/view types, action mappings,
interceptors, and so forth
To answer your question, however, it is possible to add configuration files other than the default ones by using the config initialization parameter in web.xml.
From web.xml
Key Initialization Parameters
config - a comma-delimited list of XML configuration files to load.
So it is enough to specify the new struts.xml in web.xml to achieve your goal:
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
<init-param>
<param-name>config</param-name>
<!-- Edit after #AleskandrM's comments/answer because
1) every possible configuration file must be specified,
otherwise they will be hidden by this setting and
2) settings are relative to /WEB-INF/classes/, and hence
the /WEB-INF/ must be replaced by ../ and
3) the order is important as well. You cannot extend
struts-default package in your struts.xml if it isn't loaded yet.
-->
<param-value>/WEB-INF/struts.xml</param-value>
<param-value>struts-default.xml,struts-plugin.xml,../struts.xml</param-value>
</init-param>
</filter>
That said, I generally avoid this kind of customizations: you will earn basically nothing, apart from potential drawbacks that you might be the only one in the world to get, due to having left the main road.
The correct configuration to put struts.xml directly into WEB-INF folder is:
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>config</param-name>
<param-value>struts-default.xml,struts-plugin.xml,../struts.xml</param-value>
</init-param>
</filter>
Read Andrea answer and this one to find out why.
Also the order in which you define xml files is important as well. E.g. You cannot extend struts-default package (from struts-default.xml) in your struts.xml if it isn't loaded yet.
struts.xml should only be in the classpath of the application . Its location is irrelevant.
Struts 2 loads default configuration files (struts-default.xml, struts-plugin.xml, struts.xml) using StrutsPrepareAndExecuteFilter (org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter).
To understand about loading of these files by framework -
These filenames are defined as constant in Dispatcher.class (used in StrutsPrepareAndExecuteFilter) file of Struts framework.
DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml";
init_TraditionalXmlConfigurations() method present in Dispatcher.class loads these xmls.
private void init_TraditionalXmlConfigurations() {
String configPaths = initParams.get("config");
if (configPaths == null) {
configPaths = DEFAULT_CONFIGURATION_PATHS;
}
String[] files = configPaths.split("\\s*[,]\\s*");
for (String file : files) {
if (file.endsWith(".xml")) {
configurationManager.addContainerProvider(createStrutsXmlConfigurationProvider(file, false, servletContext));
} else {
throw new IllegalArgumentException("Invalid configuration file name");
}
}
}
To Override the default path setting for these xmls you can provide the paths of these XMLs while defining the StrutsPrepareAndExecuteFilter in web.xml as answered by other users here.
Related
I already put the log4jConfigLocation in web.xml, but I still get the following warning:
log4j:WARN No appenders could be found for logger ⤦
⤥ (org.springframework.web.context.ContextLoader).
log4j:WARN Please initialize the log4j system properly.
What did I miss?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.util.Log4jConfigListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>suara2</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>suara2</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
If that's the entire log4j.properties file it looks like you're never actually creating a logger. You need a line like:
log4j.rootLogger=debug,A1
I had log4j.properties in the correct place in the classpath and still got this warning with anything that used it directly. Code using log4j through commons-logging seemed to be fine for some reason.
If you have:
log4j.rootLogger=WARN
Change it to:
log4j.rootLogger=WARN, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.conversionPattern=%5p [%t] (%F:%L) - %m%n
According to http://logging.apache.org/log4j/1.2/manual.html:
The root logger is anonymous but can be accessed with the Logger.getRootLogger() method. There is no default appender attached to root.
What this means is that you need to specify some appender, any appender, to the root logger to get logging to happen.
Adding that console appender to the rootLogger gets this complaint to disappear.
You may get this error when your log4j.properties are not present in the classpath.
This means you have to move the log4j.properties into the src folder and set the output to the bin folder so that at run time log4j.properties will read from the bin folder and your error will be resolved easily.
You'll see this warning if log4j can't find a file "log4j.properties" or "log4j.xml" anywhere.
Or, you could be doing what I did and define the logger before the log configuration file has been loaded. This would be as they say: "Putting the cart before the horse."
In the code:
public static Logger logger = Logger.getLogger("RbReport");
...
later on
PropertyConfigurator.configure(l4j);
logger = Logger.getLogger("RbReport");
Fix was to initialize the logger after the configuration was loaded.
For the geeks it was "Putting Descarte b4 d horse".
If you want to configure for the standalone log4j applications, you can use the BasicConfigurator. This solution won't be good for the web applications like Spring environment.
You need to write-
BasicConfigurator.configure();
or
ServletContext sc = config.getServletContext();
String log4jLocation = config.getInitParameter("log4j-properties-location");
String webAppPath = sc.getRealPath("/");
String log4jProp = webAppPath + log4jLocation;
PropertyConfigurator.configure(log4jProp);
If still help, verify the name of archive, it must be exact "log4j.properties" or "log4j.xml" (case sensitive), and follow the hint by "Alain O'Dea".
I was geting the same error, but after make these changes everthing works fine.
just like a charm :-).
hope this helps.
In my case the solution was easy. You don't need to declare anything in your web.xml.
Because your project is a web application, the config file should be on WEB-INF/classes after deployment.
I advise you to create a Java resource folder (src/main/resources) to do that (best pratice). Another approach is to put the config file in your src/main/java.
Beware with the configuration file name. If you are using XML, the file name is log4j.xml, otherwise log4j.properties.
Put these lines in the beginning of web.xml:
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:/main/resources/log4j.xml</param-value>
</context-param>
OK, I see a lot of answer and some very correct. However, none fixed my problem. The problem in my case was the UNIX filesystem permissions had the log4j.properties file I was editing on the server as owned by root. and readable by only root. However, the web application I was deploying was to tomcat couldn't read the file as tomcat runs as user tomcat on Linux systems by default. Hope this helps. so the solution was typing 'chown tomcat:tomcat log4j.properties' in the directory where the log4j.properties file resides.
Add log4jExposeWebAppRoot -> false in your web.xml. It works with me :)
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>path/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>log4jExposeWebAppRoot</param-name>
<param-value>false</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
I had the same problem . Same configuration settings and same warning message . What worked for me was :
Changing the order of the entries .
I put the entries for the log configuration [ the context param and
the listener ] on the top of the file [ before the entry for the
applicationContext.xml ] and it worked .
The Order matters , i guess .
I have a program I'm running in a Spring project which always fails because of a java.io.FileNotFoundException, when it comes to locating the DispatcherServlet.
The DispatcherServlet lives in the \WEB-INF folder and is accessible to the rest of the project without incident.
So at the moment I'm forced to hardcode the path to the DispatcherServlet as follows:
File config = new File("C:\\project\\build\\web\\WEB-INF\\project-servlet.xml");
boolean exists = Misc.checkFileExists(config.getAbsolutePath());
if (exists) {
System.out.println("File: " + config.getAbsolutePath() + " found.");
}
ConfigurableApplicationContext context = new FileSystemXmlApplicationContext(config.getAbsolutePath());`
Which is not the best way at all.
But if I try to place the DispatcherServlet in a folder under \WEB-INF, e.g. \WEB-INF\resources to satisfy the CLASSPATH, the file is still not found. Because of this I can't use ClassPathXmlApplicationContext.
I have resolved this by setting my web.xml file as follows:
<servlet>
<servlet-name>project</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/project-servlet.xml</param-value>
</init-param>
</servlet>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/project-servlet.xml</param-value>
</context-param>
The application works as does the test program with:
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("project-servlet.xml");
I should add that I have a single project-servlet.xml file which configures everything.
The code makes no sense. ClassPathXmlApplicationContext, as its name indicates, is used to load an XML file from a classpath resource. But you're passing it the path of a file. Read the javadoc:
Standalone XML application context, taking the context definition files from the class path, interpreting plain paths as class path resource names that include the package path (e.g. "mypackage/myresource.txt")
What constitutes the classpath of a web application is the directory WEB-INF/classes, and all the jar files inside WEB-INF/lib. So, your XML file is not in the CLASSPATH, and can thus not be loaded using a ClassPathXmlApplicationContext.
If you want to load a context file from WEB-INF, use an XmlWebApplicationContext.
You should not have to do that manually anyway, since a Spring web application is typically configured using the web.xml file, or using JavaConfig, as explained in the documentation.
I have a filter in one of the referenced libraries. I have configured this filter in web.xml of my application.
Consider I have the filter in abcd.jar.
I am configuring it to my web.xml as
<filter>
<filter-name>message</filter-name>
<filter-class>com.test.myfilter</filter-class>
<init-param>
<param-name>message</param-name>
<param-value>A message for you!</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>message</filter-name>
<url-pattern>/test/filter2*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
When browsed the url containing the match localhost:8080/test/filter2.jsp. I could access this correctly. But not sure whether my filter is called successfully or not.
I cannot test it by adding the print statements in the filter class because it is from referenced libraries.
Is there any other way to test it.
Create method break-point in your third party jar file. And then wait to see if the break-point is triggered or not.
For creating the break-point in third party library in eclipse, open the class file in your jar in project explorer, then open the outline, right click and add the break-point.
however tomcat is throwing the error :
IOException parsing XML document from ServletContext resource [/WEB-INF/applicationContext.xml];
Which suggests that tomcat expects the applicationContext.xml to be one directory above where it is copied to. It is being copied to the /WEB-INF/classes directory, not just the plain old /WEB-INF
I am using maven.
If you have put it under src/main/resources, you should refer to the resource as classpath:/applicationContext.xml
In your web.xml you can state where your applicationContext.xml is located. If it is in /WEB-INF/classes then you must state /WEB-INF/classes/applicationContext.xml (and not just /WEB-INF/applicationContext.xml).
Try this:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
To include more than one context files you can use the import function. To do so, write into your applicationContext.xml one line per file like this:
<import resource="myOtherSpringContext.xml"/>
Use the following syntax in your web.xml ( http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/context/ContextLoader.html ):
<!-- list of the configuration files to load -->
<context-param>
<!-- Spring -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>
It will load it from the classes/* directory.
BTW, if you want to copy the applicationContext.xml directly in your WEB-INF directory, move it in /src/main/webapp
BTW, here is the way recommanded by the spring documentation: http://static.springsource.org/spring/docs/3.0.x/reference/beans.html#context-create
HIH
This is standard Maven behaviour, and is what a lot of people use with no objection. Why do you prefer it in WEB-INF?
Anyway, if you want it there, you can just put it in src/main/webapp/WEB-INF.
the standard way is to create new source dir src/main/webapp. All files from this dir will be places in the same folder as WEB-INF in resulting war. So, inside this new source dir you can create WEB-INF and place you applicationcontext.xml in it.
so you structure would look much like
+src
+---main
+---+---java
+---+---webapp
+---+------WEB-INF
check maven-war-plugin documentation
When I'm writting
<init-param>
<param-name>config</param-name>
<param-value>WEB-INF/struts-config.xml</param-value>
</init-param>
This tag in web.xml that time I was getting the error
word config notspelled correctly
I know this is a logical name, so you can use any word, but that word
config is underlined in red. Because of that, whenever I run a struts application, I mention the path in a form tag of jsp: something like /book. This book path is also in
the struts-config.xml file.
So when I run this project, I'm getting the error
requested resources not available(/book)
That means struts-config.xml is not loaded correctly. I have imported jar also.
Try this
<init-param>
<param-name>config</param-name>
<param-value>classpath:struts-config.xml</param-value>
</init-param>
Copy struts-config.xml to WEB-INF/classes folder
Also you should have all struts jar files into your WEB-INF/lib
I don't think so it is necessary to move struts-config.xml file somewhere.
Actually word "config" is for initialize parameter(struts-config.xml) with name config.
config with orange color(not red)underline is only for dictionary check nothing else.
So error occurs because
In your struts-config.xml has mess or misconfigured.if possible please add you struts-config.xml with this thread so we can check what actually a reason.
Put it inside servlet action with servlet-class ActionServlet. Worked in my case, have similar problem, but I've just wanted to change folder from classes to my default.
<init-param> <param-name>StrutsConfig</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param>