I have a Spring + Jersey web application that I'm migrating from a web.xml to annotation base configuration. I'm implementing WebApplicationInitializer and everything works except log4j, because I have a custom file name.
In the web.xml I had
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>/WEB-INF/custom-name-log4j.xml</param-value>
</context-param>
This worked.
Now, I tried to do the same in Java:
container.setInitParameter("log4jConfiguration", "/WEB-INF/custom-name-log4j.xml");
This doesn't work… I get the following errors in Tomcat 7.0.62:
ERROR StatusLogger No Log4j context configuration provided. This is very unusual.
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
My WAR file contains the xml in the WEB-INF/ folder.
Do I have to do more than specifying that log4jConfiguration parameter?
Later Edit:
WebApplicationInitializer
@Override
public void onStartup(ServletContext container) {
AnnotationConfigWebApplicationContext rootContext =
new AnnotationConfigWebApplicationContext();
rootContext.register(MyApplicationConfiguration.class);
container.setInitParameter("log4jConfiguration", "/WEB-INF/custom-name-log4j.xml");
rootContext.setConfigLocation("my.package.spring");
final FilterRegistration.Dynamic characterEncodingFilter = container.addFilter("characterEncodingFilter", new CharacterEncodingFilter());
characterEncodingFilter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
characterEncodingFilter.setInitParameter("encoding", "UTF-8");
characterEncodingFilter.setInitParameter("forceEncoding", "true");
container.setInitParameter("spring.profiles.default", "prod");
rootContext.register(SecurityContextFilter.class);
container.addListener(new ContextLoaderListener(rootContext));
container.addListener(new RequestContextListener());
container.setInitParameter("contextConfigLocation", "");
final ServletContainer servlet = new ServletContainer();
final ServletRegistration.Dynamic appServlet = container.addServlet("appServlet", servlet);
appServlet.setInitParameter("jersey.config.server.provider.packages", "my.package");
appServlet.setLoadOnStartup(1);
final Set<String> mappingConflicts = appServlet.addMapping("/rest/*");
}
Best Answer
You also need to register a Listener :
Log4jConfigListener
(you can find it in org.springframework.web.util)By the way, you can note that it is deprecated since spring 4.2.1
EDIT
Sorry I didn't realized that you were using log4j2, everything stated above is false, and here is the solution for you :
log4j2 (thanks to
log4j-web
artifact) & spring are both relying onServletContainerInitializer
fromservlet 3.0
API to setup theServletContext
. The problem is that the order they are executed depends on the order they are scanned on the classpath and you can't really rely on it (in your case theLog4jServletContainerInitializer
startup methods is called before the one fromSpringServletContainerInitializer
).To correct this you can declare your own
ServletContainerInitializer
implementation which we'll be taken into account before others (before scanning the classpath) and here is a sample :Then you have to create a file :
/META-INF/services/javax.servlet.ServletContainerInitializer
and put into it :
example.initializer.Log4j2ConfigServletContainerInitializer
(change to suit your needs)and the configuration you provided to set a custom log4j config file location will be set before triggering the
Log4jServletContainerInitializer
and everything is going to be fine.see :
https://docs.oracle.com/javaee/6/api/javax/servlet/ServletContainerInitializer.html
http://www.eclipse.org/jetty/documentation/current/using-annotations.html#servlet-container-initializers
http://logging.apache.org/log4j/2.x/manual/webapp.html
EDIT
POC @ http://www.filedropper.com/32713596_1 just run
mvn jetty:run