Log4j2 configuration location with JVM arguments for Web application that uses Spring Framework 5.2 - spring

I am upgrading log4j 1.2 to log4j 2.17.1 for a Spring Web application Servlet - 3.1 and Spring 5.2.2
1- The log4j2.xml file with all the configurations for Appenders etc is in a file outside the classpath(external file in the deployed server) - example - /tomcat/conf/log4j2.xml
Previously log4j was configured using this following JVM argument -
-Dlog4j.configuration = file:/opt/tomcat/conf/log4j.xml
I am just gonna change this to -
-Dlog4j.configuration = file:/opt/tomcat/conf/log4j2.xml
Question is, is this change enough for the new log4j2.xml to be used now. All the other stuff in the project is setup.
Do I need any more changes in web.xml etc, If I am already using this JVM argument ?

Related

Jersey compatibility with log4j2 - failing to start servlets

I'm having issues getting Jersey 1.19 to work with log4j2 on Tomcat7. My project's working assembly against log4j1 consists of the following:
slf4j-api: 1.5.6
slf4j-log4j12: 1.5.6
log4j: 1.2.14
I have a test project using log4j2 working successfully (logs are written to a file) with the following:
slf4j-api: 1.5.6
slf4j-log4j12: 1.5.6
log4j-1.2-api: 2.11.0
log4j-api: 2.11.0
log4j-core: 2.11.0
I am including log4j-1.2-api and the slf4j-log4j12 for the 'bridge' between log4j 1 and 2 per documentation, as there is legacy code I am unable to touch that uses log4j1.
As soon as I remove log4j 1.2.14 from my real project's assembly, and add in the bridge (log4j-1.2-api) and the api and core for log4j2, I run into the following exception when the the first HTTP request hits the server after startup. Reverting back to log4j1 resolves the issue.
My log4j2.xml file (which works on the test project) is located in the servlets /WEB-INF/classes folder. I've also tried it in the /WEB-INF folder.
asm.jar is 3.3.1 if that matters - I see it in the stacktrace.
Is there a compatibility issue I haven't read about getting these to play together?
java.lang.IllegalArgumentException
jersey.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:170)
jersey.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:153)
jersey.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:424)
com.sun.jersey.spi.scanning.AnnotationScannerListener.onProcess(AnnotationScannerListener.java:138)
com.sun.jersey.core.spi.scanning.JarFileScanner.scan(JarFileScanner.java:97)
com.sun.jersey.spi.scanning.servlet.WebAppResourcesScanner$1.f(WebAppResourcesScanner.java:94)
com.sun.jersey.core.util.Closing.f(Closing.java:71)
com.sun.jersey.spi.scanning.servlet.WebAppResourcesScanner.scan(WebAppResourcesScanner.java:92)
com.sun.jersey.spi.scanning.servlet.WebAppResourcesScanner.scan(WebAppResourcesScanner.java:79)
com.sun.jersey.api.core.ScanningResourceConfig.init(ScanningResourceConfig.java:80)
com.sun.jersey.api.core.servlet.WebAppResourceConfig.init(WebAppResourceConfig.java:102)
com.sun.jersey.api.core.servlet.WebAppResourceConfig.<init>(WebAppResourceConfig.java:89)
com.sun.jersey.api.core.servlet.WebAppResourceConfig.<init>(WebAppResourceConfig.java:74)
com.sun.jersey.spi.container.servlet.WebComponent.getWebAppResourceConfig(WebComponent.java:668)
com.sun.jersey.spi.container.servlet.ServletContainer.getDefaultResourceConfig(ServletContainer.java:435)
com.sun.jersey.spi.container.servlet.ServletContainer.getDefaultResourceConfig(ServletContainer.java:602)
com.sun.jersey.spi.container.servlet.WebServletConfig.getDefaultResourceConfig(WebServletConfig.java:87)
com.sun.jersey.spi.container.servlet.WebComponent.createResourceConfig(WebComponent.java:699)
com.sun.jersey.spi.container.servlet.WebComponent.createResourceConfig(WebComponent.java:674)
com.sun.jersey.spi.container.servlet.WebComponent.init(WebComponent.java:205)
com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:394)
com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:577)
javax.servlet.GenericServlet.init(GenericServlet.java:158)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2549)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2538)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:748)
TL;DR: Although Jersey 1.19.x can scan classes compiled with JDK 1.8, it fails on multi-release classes in META-INF/versions/9 compiled with JDK 9.
Remark: although this is an old question, even today there are some application using Jersey 1.19.x. Due to security problems they should upgrade to Log4j2 version 2.12.4 immediately if the run on Java 7 (which is itself a security risk) or the latest version if they run on Java 8+ (2.17.2 at the moment of writing). Since Jersey 1.19.x has no known security problems, its upgrade can be performed at a later time.
You have the same problem as in LOG4J2-3445: Log4j2 artifacts are multi-release, which means that most of the classes are compiled with Java 8 (supported by your old Jersey release), but some (in /META-INF/versions/9) are compiled with Java 9. The class scanner included in your Jersey version can not parse them.
You can try multiple workarounds:
Let Tomcat scan the classes instead of Jersey. This is available since Servlet 3.0 (Tomcat 7). To enable container annotation scanning in Jersey declare your servlet without a <servlet-class> parameter and a <servlet-name> equal to javax.ws.rs.core.Application:
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>
This should also save up some startup time, since multiple Java EE technologies can profit of a single class scan.
If the workaround above does not solve your problem, you can restrict the paths scanned by Jersey using the com.sun.jersey.config.property.classpath servlet parameter (cf. javadoc). A setting of "/WEB-INF/classes" should be enough for most purposes.

spring-boot - External log4j configuration not working

I am trying to do a setup for production environment, so I wanted to keep log4j.properties out of my application jar file.
For that I have kept my application.properties and log4j.properties files parallel to my spring-boot jar file. And I have given logging.config: file:log4j.properties in my application.properties. This doesn't seem to work. Spring is still picking up the log4j.properties file which is placed inside the jar file.
I have tried giving the absolute path in logging.config property like C:\Users\furquan\project\jars\log4j.properties, but it still the log4j.properties that was being used was the one inside the jar file.
Please help, its important !!!
-Dlogging.config=/path/to/log4j.properties
Or you can specify it in your application.properties or bootstrap.properties.
From 26.5 Custom log configuration
And just a note:
After spring boot 1.4, Log4j 1 support has been removed. So maybe you can consider use the default logback, or use log4j2 instead.

Springboot externalizing log4j configuration

In a springboot application, I have a single jar, and then a subdirectory config with application.properties, applicationContext.xml, and log4j...properties file.
I am trying to externalize the log4j config. The application.properties is externalized this way.
But, when springboot runs it is using the log4j config file from within the jar file. By using the -Dlog4j.debug option I can see that log4j uses my external file first, but when spring starts it overrides the log4j setting with the one in the jar.
here is an example startup (with all options)
java -Dlog4j.debug
-Dlogging.config="file:/opt/config/log4j-qa.properties"
-Dlog4j.configuration="file:/opt/config/log4j-qa.properties"
-jar /opt/myjarName.jar
--spring.config.location=/opt/config/
on first startup log4j states
log4j: Reading configuration from URL file:/opt/config/log4j-qa.properties
then on springboot start
log4j: Reading configuration from URL jar:file:/opt/dms-events-api.jar!/log4j-qa.properties
but I want it to read only the external file file:/opt/config/log4j-qa.properties
resolution:
In our application we had line
#ImportResource("classpath:applicationContext.xml")
which then defined the log4j properties file from the classpath:
the simple solution
1. create a /config directory at the root of the api application and put the properties files there
2. remove the ImportResource line, it isn't needed now
3. add a line to the the application.properties file
logging.config=file:config/log4j-${our environment var}.properties
the explanation
By creating a /config directory at the root of the project then
we can work in eclipse as usual and find our properties files.
--and then to externalize configs
simply add a config directory off of where the application jar is and put properties files there.
Two problems are there:
Configuration for externalise: - Tried and works below one for me in spring boot jar
-Dlog4j.configuration=file:/Users/test/Any-Folder/log4j.properties
Spring logging takes over - for that you need to exclude the logging module. PFB the config for Gradle build.
configurations {
all*.exclude module : 'spring-boot-starter-logging'
}

Camel log component with log4j2

I have a spring-boot application with apache camel and log4j2 as the underlying log provider. Is it possible to use camel log component to write to the log files as configured by the log4j2.xml?
Below jar files are there in the classpath:-
log4j-over-slf4j-1.7.16.jar
logback-classic-1.1.5.jar
logback-core-1.1.5.jar
log4j-api-2.4.1.jar
log4j-core-2.4.1.jar
jcl-over-slf4j-1.7.16.jar
jul-to-slf4j-1.7.16.jar
slf4j-api-1.7.16.jar
You currently have two logger implementations configured: Log4j 2 and Logback. If you want to do all your logging with Log4j2 then you need to add the Log4j SLF4J bridge and remove the Logback jars. I also recommend you use the latest Log4j 2 version (2.6.1). That gives the following dependencies:
log4j-api-2.6.1.jar
log4j-core-2.6.1.jar
log4j-slf4j-impl-2.6.1.jar (routes SLF4J API calls to Log4j 2)
log4j-jcl-2.6.1.jar (routes Commons Logging API calls to Log4j 2)
log4j-jul-2.6.1.jar (also set system property java.util.logging.manager to org.apache.logging.log4j.jul.LogManager)
slf4j-api-1.7.16.jar
You don't need:
log4j-over-slf4j-1.7.16.jar
logback-classic-1.1.5.jar
logback-core-1.1.5.jar
jcl-over-slf4j-1.7.16.jar
jul-to-slf4j-1.7.16.jar
About configuration, by default Log4j2 looks for a file called log4j2.xml in the classpath, but you can also specify the location with a system property.
The Log4j 2 manual is much better than the Log4j 1 documentation and shows many example configurations.

Spring Boot and Jboss wildfly setting the context root

I am trying to set the context root of my spring boot application. I'm deploying my application as a war file to Jboss.
i've tried to set the contextPath of what I'd like my root URL to be when deploying it to JBoss/Wildfly but it seems to get ignored. Unless I add a jboss-web.xml file setting a contex-root variable, my deployment url is always based on the war file name:
e.g. : myapp.war always deploys as : localhost:8080/myapp unless I use jboss-web. I've tried setting the contextPath in the server.properties file and it doesn't seem to work.
My question is should I be able to? I'm using the latest Spring Boot.
In other words, add your jboss-web.xml
file in this directory : /src/main/webapp/WEB-INF
Content of your jboss-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<context-root>/</context-root>
</jboss-web>
All of the server.* properties that Spring Boot supports only apply to the configuration of the embedded servlet container (Tomcat, Jetty, or Undertow). If you're deploying your Spring Boot app to a standalone server then you'll need to configure that server using whatever mechanisms it provides.

Resources