Log4J2 in Spring Boot with embedded Tomcat - spring-boot

I am trying to let the embedded Tomcat in Spring Boot log to my Log4J2 configuration, but it doesn't work.
According to this answer that copes with an external Tomcat: https://stackoverflow.com/a/28639068/1845463 there seems to be the need to move some jars to $Catalina_home/libs etc. I think this is not possible with Spring Boot, isn't it?
Has someone managed to get log4j2 running and be able to configure appenders for catalina log?
Thanks in advance

EDITED: The simplest way to do is to add spring-boot-starter-log4j2.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
N.B. Make sure that the other components don't need different version of log4j. This may cause run-time errors. e.g. elasticsearch java API requires 2.6+ and spring-boot-starter-log4j2:1.3.8 provides log4j:2.4.1, if we're building an app that connects elasticsearch and uses spring boot too. Then we will end up getting NoSuchMethodError or similar errors. For resolution of those errors we should add log4j2:2.6+ in our pom.

Which Spring Boot version are you using? I believe 1.4.x.RELEASE uplifted it to log4j2.
As #M.Deinum mentioned including:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
brings in:
log4j-core, log4j-api and a few more. See https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j2/1.4.6.RELEASE
It might be advisable to exclude logging starter using:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

Related

change default web server on spring-boot 2.4.4

I'm working with Spring Boot 2.4.4 and I would change the default web server Tomcat to undertow orJHetty but I find it very difficult using both Gradle or Maven.
An old documentation exposes how do it but I'm sure all is changed because now tomcat, undertow and jetty configuration is embedded in the core library:
https://docs.spring.io/spring-boot/docs/2.1.9.RELEASE/reference/html/howto-embedded-web-servers.html
How do it in the 2.4.4 version?
There are no changes between the versions. This is well described right at the Spring Boot 2.4.4 Reference guide, right in 3.1. Use Another Web Server section. Basically, the change consists of two steps:
Exclude embedded Tomcat server dependency from the spring-boot-starter-web artifact:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- Exclude the Tomcat dependency -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
Include your embedded server as a separate dependency instead:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
Just don't forget to notice the following quote from the reference guide in the very same section which might or might not be relevant to you:
The version of the Servlet API has been overridden as, unlike Tomcat 9 and Undertow 2.0, Jetty 9.4 does not support Servlet 4.0.
follow three steps to change the default web server, change configuration in pom.xml.
1.exclude the default web server.
2.Include the necessary web server.
3.Maven update.
For example,
Instead of this
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
Add this one
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
for the necessary server add the appropriate web server dependency.

ERROR:The type org.apache.log4j.Logger cannot be resolved. It is indirectly referenced from required .class files

Trying to upgrade a project from using Camel v2.21.2 to using Camel v2.22.0
This entails going from Spring v4.x to v5.x and from Spring-boot v1.5.x to Spring-boot v2.0.4.RELEASE.
Project uses groovy-all 2.4.15. We are not using log4j in our project, we are using slf4j-api(1.7.25) and logback(1.2.3) in our project. Yet, running a Maven install is giving an error saying that some class is using log4j
When I added log4j(1.2.17) dependency it is working fine but we don't want to add it.
Is there something that can be excluded from the spring-boot starter? Any other solutions? Any hints on how to diagnose the problem?
I think log4j or log4j2 should be in the classpath. Spring Boot v2.0.x has log4j2 added. If log4j2 is not compatible with Camel version. Exclude the log4j2 and add log4j dependency and try . Hope it should work..!
<!-- Exclude Spring Boot's Default Logging -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Add Log4j Dependency -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
</dependency>

Spring Boot logging with Log4j2

Written simple POC to prove and test Spring Boot and log4j2 compatibility. Once successful I will move it to real application.
Please refer my POC source code:
https://github.com/Dennyss/SpringBootLog4j2POC
I know/read about Spring version and log4j2 compatibility from:
How to set up Spring Boot and log4j2 properly?
Found and tried recommendations described here:
Spring-Boot logging with log4j2?
But still not working. The problem is that both application logs and Spring logs are printing to console only.
Please refer maven dependencies below (from POC):
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.6.2</version>
</dependency>
</dependencies>
If I don't exclude Spring's logback and don't add boot-starter-log4j2 then application logs are printing to application file but Spring logs are not printing at all. I feel the problem somewhere with dependencies. Appreciate any help.
According to the Spring Boot Logging documentation, the location of the logging configuration file can be specified using the logging.config property. I noticed that your start.sh script is passing -Dlog4j.configurationFile. Normally, this would be sufficient for direct Log4J 2 integration, but Spring Boot uses logging.config.
After switching to this, it writes to the log files:
java -Dlogging.config=/share/LogPOC/log4j2.xml -cp poc.jar:libs/* com.poc.logger.Application

Spring Boot Servlet API Version

I'm trying to run a Spring Boot app on Tomcat 7. From my understanding, it should be compatible with servlet 3.0 spec.
In my dependency, I mark tomcat as provided:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope> <!-- Mark as provided so it doesn't interfere when we deploy in container -->
</dependency>
Edit: And I've added the property <tomcat.version>7.0.59</tomcat.version>
But I still can't start it in tomcat. I'm getting this error:
Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName()Ljava/lang/String;
at org.apache.tomcat.websocket.server.WsServerContainer.(WsServerContainer.java:147)
at org.apache.tomcat.websocket.server.WsSci.init(WsSci.java:131)
at org.apache.tomcat.websocket.server.WsSci.onStartup(WsSci.java:47)
Which are because it apparently needs servlet spec 3.1.
Am I missing something?
The problem is, spring-boot also configure websocket support on spring-boot-starter-tomcat, which is includes by spring-boot-starter-web. And according to Apache, you must use Java 7 if you want web socket with Tomcat 7.
Here: http://tomcat.apache.org/whichversion.html
Either compile with Java 7 or exclude websocket support
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
</exclusion>
</exclusions>
</dependency>

Does having spring-boot-actuator changes the context root of the spring application?

According to this post, by having the spring-boot-actuator dependency in pom.xml, I could benefits from the actuator endpoints. However, I observed it breaks my existing my spring application (It is not a spring-boot application).
I added the following to my dependency in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
<version>1.2.5.RELEASE</version>
</dependency>
Thats it. I did not make any changes to application yet.
I started the container using maven-t7-plugin.
Now my application endpoint http://localhost:8010/mycontext/foo is returning 404. I commented out the above dependency in pom.xml.
Now my application returns 200 OK for the above request.
Kindly help troubleshoot me as what is going wrong. I could not find any obvious reasons.
Thanks
When I looked at the spring logs in console, I noticed the following:
WARN org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/mycontext/foo] in DispatcherServlet with name 'DispatcherServlet'.
Since I have configured DispatcherServlet in my Spring application, I cannot use auto-configure of spring-boot-actuator.
Once I excluded that dependency, my application works as expected.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
<version>1.2.5.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</exclusion>
</exclusions>
</dependency>

Resources