I’m following the “Piping to Log4j using SLF4J” directions from the Vaadin website (https://vaadin.com/docs/v8/framework/advanced/advanced-logging.html#advanced.logging.slf4j), and have scoured the web, but haven’t had any luck getting this to work. Interestingly, after adding the VaadinServlet, the Spring annotations within classes annotated with @Route are no longer triggered, e.g., @Autowired and @PostConstruct. With regards to Spring-Boot, how can I get my servlet to behave like the default servlet that is auto-registered when not implementing my own?
Another factor that might be coming into play is that when trying to override the logging’s automatic loading and force set the configuration, I get the following output to stderr, but no exception is thrown “com.google.common.flogger.backend.log4j2.Log4j2BackendFactory.create SLF4JLogger cannot be cast to org.apache.logging.log4j.core.Logger” and it makes me wonder if Java’s/Vaadin’s logging is not propagating these messages back up the stack.
I started off trying to implement Google’s Flogger API with Log4J2 with Vaadin 16. This problem occurred and then just tried implementing Log4J2 with SFL4J Binding as suggested in the documentation. Same problem. Can anyone point me to a FULL sample project or codebase that accomplishes this?
Thanks in advance!
VaadinServlet:
@WebServlet(value = "/*", asyncSupported = true)
public class AppServlet extends VaadinServlet implements SessionInitListener {
private static final long serialVersionUID = 3469585746542555263L;
static {
SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
java.util.logging.Logger.getGlobal().setLevel(Level.FINEST);
}
@Override
protected void servletInitialized() throws ServletException {
super.servletInitialized();
getService().addSessionInitListener(this);
}
@Override
public void sessionInit(SessionInitEvent event) throws ServiceException {
VaadinSession session = event.getSession();
NotificationErrorHandler errHandler = new NotificationErrorHandler();
session.setErrorHandler(errHandler);
}
}
Spring-Boot the VaadinServlet:
@Configuration
public class AppConfiguration {
@Bean
public ServletRegistrationBean<AppServlet> flexmonsterServlet() {
ServletRegistrationBean<AppServlet> servRegBean = new ServletRegistrationBean<>();
servRegBean.setServlet(new AppServlet());
servRegBean.addUrlMappings("/*");
servRegBean.setName("appServlet");
servRegBean.setLoadOnStartup(1);
return servRegBean;
}
}
Logging Service:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class LoggingService {
private static final Logger logger = LoggerFactory.getLogger(LoggingService.class);
public void log(String msg, Level level) {
switch (level.getName()) {
case "INFO":
logger.info(msg);
break;
case "WARNING":
logger.warn(msg);
break;
case "SEVERE":
logger.error(msg);
break;
case "FINE":
logger.debug(msg);
break;
case "FINER":
logger.debug(msg);
break;
case "FINEST":
logger.debug(msg);
break;
case "CONFIG":
logger.debug(msg);
break;
}
}
}
src/main/resources/log4j2.properties
status=error
name=PropertiesConfig
property.filename=./target/logs
filter.threshold.type=ThresholdFilter
filter.threshold.level=debug
# ConsoleAppender will print logs on console
appender.console.type=Console
appender.console.name=consoleLogger
appender.console.layout.type=PatternLayout
appender.console.layout.pattern=%m%n
appender.console.filter.threshold.type=ThresholdFilter
appender.console.filter.threshold.level=error
# RollingFileAppender will print logs in file which can be rotated based on time or size
appender.rolling.type=RollingFile
appender.rolling.name=fileLogger
appender.rolling.fileName=${filename}/app.log
appender.rolling.filePattern=${filename}/app-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz
appender.rolling.layout.type=PatternLayout
appender.rolling.layout.pattern=%d %p %C{1.} [%t]
%m%n
appender.rolling.policies.type=Policies
appender.rolling.policies.time.type=TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval=2
appender.rolling.policies.time.modulate=true
appender.rolling.policies.size.type=SizeBasedTriggeringPolicy
appender.rolling.policies.size.size=100MB
appender.rolling.strategy.type=DefaultRolloverStrategy
appender.rolling.strategy.max=5
# Mention package name here. Classes in this package or subpackages will use ConsoleAppender and RollingFileAppender for logging
logger.rolling.name=com.example.app
logger.rolling.level=debug
logger.rolling.additivity=false
logger.rolling.appenderRef.rolling.ref=fileLogger
logger.rolling.appenderRef.rolling.ref=consoleLogger
# Configure root logger for logging error logs in classes which are in package other than above specified package
rootLogger.level=info
rootLogger.additivity=false
rootLogger.appenderRef.rolling.ref=fileLogger
rootLogger.appenderRef.console.ref=consoleLogger
pom.xml:
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/jul-to-slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.30</version>
</dependency>
Psuedo-code showing attempt to load file:
LoggerContext context = (org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
File file = new File("path/to/a/different/log4j2.properties");
// this will force a reconfiguration
context.setConfigLocation(file.toURI());