Spring 5 Logging using Logback without using Spring Boot



In the previous article, we have secured the REST API with Spring Security and JSON Web Token (JWT). Now we are gonna add logging support using the Logback logging framework since there is some issue with the Log4j dependencies in the application.

What is Logback?

Logback is a logging framework for Java applications, created as a successor to the popular log4j project.

Configure Logback

Add Dependencies

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javachinna</groupId>
	<artifactId>spring-rest-jwt-demo</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-rest-jwt-demo Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<properties>
		<java-version>11</java-version>
		<spring.version>5.2.3.RELEASE</spring.version>
		<hibernate.version>5.4.1.Final</hibernate.version>
		<slf4j.version>1.7.25</slf4j.version>
	</properties>
	<dependencies>
		<!-- Spring Web MVC -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- Required for converting JSON data to Java object and vice versa -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.9.10.1</version>
		</dependency>
		<!-- Servlet API -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.0.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>1.2.3</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jul-to-slf4j</artifactId>
			<version>${slf4j.version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>log4j-over-slf4j</artifactId>
			<version>${slf4j.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.9.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<version>2.1.8.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>${hibernate.version}</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.14</version>
			<scope>runtime</scope>
		</dependency>
	</dependencies>
	<build>
		<finalName>SpringRestJwt</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>${java-version}</source>
					<target>${java-version}</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>src/main/webapp</warSourceDirectory>
					<warName>SpringRestJwt</warName>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Configuration Options

We can configure Logback either programmatically or with a configuration script expressed in the XML or Groovy format.

Let us see the configuration process:

  1. Logback seeks the logback-test.xml in the classpath.
  2. If no such file is found, it looks further for the file called logback.groovy in the classpath.
  3. If no such file is found, it looks further for the file called logback.xmlin the classpath.
  4. If none of the above succeeds, Logback starts to use the BasicConfigurator, which sets up the framework to redirect the logging output to the console.

We can check this behavior with the following code snippet

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);

Output

12:30:18,699 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
12:30:18,700 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
12:30:18,701 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml]
12:30:18,709 |-INFO in ch.qos.logback.classic.BasicConfigurator@2084918d - Setting up default configuration.

Configure with XML

Let us configure Logback with logback.xml file

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

As you can see above, We have set the logging level to debug to enable debug logging.

The available logging levels in Logback are:

  • OFF (output no logs)
  • ERROR
  • WARN
  • INFO
  • DEBUG
  • TRACE

Build Application

Run mvn clean install command to clean and build the war file

Deploy Application

Deploy the generated war file in a server like tomcat.

Test Application

Generate a JSON Web Token – Create a POST request with URL localhost:8080/authenticate. The request body should have a valid username and password. In our case username is javachinna and the password is password.

Hit the url http://localhost:8080/SpringRestJwt/greet/Chinna with the generated JWT token

Logs

29-07-2020 20:20:49.084 [http-nio-8080-exec-18] DEBUG o.s.web.servlet.DispatcherServlet.traceDebug - GET "/SpringRestJwt/greet/Chinna", parameters={}
29-07-2020 20:20:49.084 [http-nio-8080-exec-18] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping.getHandler - Mapped to com.javachinna.controller.GreetController#greet(String, ModelMap)
29-07-2020 20:20:49.125 [http-nio-8080-exec-18] INFO  c.j.controller.GreetController.greet - Hello!!! Chinna How are You?
29-07-2020 20:20:49.129 [http-nio-8080-exec-18] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor.writeWithMessageConverters - Using 'application/json', given [*/*] and supported [application/json, application/*+json]
29-07-2020 20:20:49.130 [http-nio-8080-exec-18] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor.traceDebug - Writing ["Hello!!! Chinna How are You?"]
29-07-2020 20:20:49.131 [http-nio-8080-exec-18] DEBUG o.s.s.w.h.writers.HstsHeaderWriter.writeHeaders - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@666f054
29-07-2020 20:20:49.132 [http-nio-8080-exec-18] DEBUG o.s.web.servlet.DispatcherServlet.logResult - Completed 200 OK
29-07-2020 20:20:49.133 [http-nio-8080-exec-18] DEBUG o.s.s.w.a.ExceptionTranslationFilter.doFilter - Chain processed normally
29-07-2020 20:20:49.133 [http-nio-8080-exec-18] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter.doFilter - SecurityContextHolder now cleared, as request processing completed

Source code

https://github.com/JavaChinna/spring-rest-logging

References

https://dzone.com/articles/using-logback-with-spring

Conclusion

That’s all folks. In this article, we have added logging support using the Logback framework.

Please share the article with your friends if you like it. Thank you for reading.

Read Next:  Spring 5 REST API with Embedded Tomcat without using Spring Boot

Leave a Reply