I'm trying to Initialize Log4j by Combining Configuration File with Programmatic Configuration.
I followed the manual (though it's syntax isn't quite right and it's outdated), which resulted in the following classes:
CustomConfigurationFactory.java:
package factory;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.Order;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import java.net.URI;
@Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
@Order(1)
public class CustomConfigurationFactory extends ConfigurationFactory {
/**
* Valid file extensions for XML files.
*/
private static final String[] SUFFIXES = new String[]{".xml", "*"};
/**
* Return the Configuration.
*
* @param source The InputSource.
* @return The Configuration.
*/
public Configuration getConfiguration(LoggerContext context, ConfigurationSource source) {
return new CustomConfiguration(context, source);
}
/**
* Returns the file suffixes for XML files.
* @return An array of File extensions.
*/
public String[] getSupportedTypes() {
return SUFFIXES;
}
}
CustomConfiguration.java:
package factory;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
import java.util.Map;
public class CustomConfiguration extends XmlConfiguration {
CustomConfiguration(LoggerContext context, ConfigurationSource configSource) {
super(context, configSource);
}
@Override
protected void doConfigure() {
super.doConfigure();
final LoggerConfig rootLogger = getRootLogger();
final Map<String, Appender> appenderMap = rootLogger.getAppenders();
if (MainClass.DEBUG) {
rootLogger.addAppender(appenderMap.get("Console"), Level.ALL, null);
} else {
rootLogger.addAppender(appenderMap.get("Mail"), Level.ERROR, null);
}
}
}
Now, when running this and calling ConfigurationFactory.setConfigurationFactory(new CustomConfigurationFactory())
before any calls to the Logging API, I'm getting output to the console in the form of
ERROR StatusLogger Reconfiguration failed: No configuration found for 'someNumbersAndChars' at 'null' in 'null'
While debugging this, I found out that this is printed the first time I'm acquiring a Logger
. The reason for that is that, if a custom ConfigurationFactory
is supplied, the implementation of ConfigurationFactory.getConfiguration(LoggerContext, String, URI)
by ConfigurationFactory
's private subclass Factory
(which is the default factory) will be overridden by ConfigurationFactory
's implementation.
And ConfigurationFactory
's implementation simply returns null
if the URI is so, while ConfigurationFactory.Factory
's implementation nevertheless returns a valid configuration.
My first idea now would be to override these overloads of ConfigurationFactory.getConfiguration()
in my custom factory, but there has to be another way, right? ;)