Hi, I'm using log4j2-beta9 and want to configure it using a log4j2.xml in strict mode. My issue is: how do I specify attributes that are not in the shipped schema file? An Example: <?xml version="1.0" encoding="UTF-8" ?> <Configuration status="DEBUG" strict="true" monitorInterval="5" name="TestingAttributes" verbose="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Log4j-config.xsd"> <Properties> </Properties> <Appenders> <Appender type="Console" name="SYSERR" target="SYSTEM_ERR"> <!-- cvc-complex-type.3.2.2: Attribute 'target' is not allowed to appear in element 'Appender'. --> <Layout Type="PatternLayout"> <Pattern>%date{dd.MM.yyyy HH:mm:ss,SSS} %5p %logger %m%n</Pattern> </Layout> <Filters> <Filter type="MarkerFilter" marker="FLOW" onMatch="DENY"
onMismatch="NEUTRAL" /> <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="DENY" onMismatch="NEUTRAL" /> </Filters> </Appender> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="SYSERR" /> </Root> </Loggers> </Configuration> Notice that I want to set the appender to have the target SYSTEM_ERR but the attribute is not allowed in strict mode. target="SYSTEM_ERR"> <!-- cvc-complex-type.3.2.2: Attribute 'target' is not allowed to appear in element 'Appender'. --> I could always edit the Log4j-config.xsd and allow that attribute there but that would be kind of wrong also because not all appenders have a target attribute. As searching the web didn't help me so far, I'm asking you: Is there anything I'm missing in configuring Log4j2 in strict XML mode? I am for now using the following classes as a workaround: import org.apache.logging.log4j.core.config.*; import org.apache.logging.log4j.core.config.plugins.*; /** * Simple ConfigurationFactory that returns a {@link StrictXMLConfigurationFactory} * * @author <a href="mailto:alexander.rat...@materna.de">Alexander Rathai</a> */ @Plugin(name = "StrictXMLConfigurationFactory", category = "ConfigurationFactory") @Order(4) public class StrictXMLConfigurationFactory extends ConfigurationFactory { /** * Valid file extensions for XML files. */ public static final String[] SUFFIXES = new String[]{".xml"}; /** * @see org.apache.logging.log4j.core.config.ConfigurationFactory#getConfiguration(org.apache.logging.log4j.core.config.ConfigurationFactory.ConfigurationSource) */ @Override public Configuration getConfiguration(ConfigurationSource source) { return new StrictXMLConfiguration(source); } /** * @see org.apache.logging.log4j.core.config.ConfigurationFactory#getSupportedTypes() */ @Override public String[] getSupportedTypes() { return XMLConfigurationFactory.SUFFIXES; } } And import java.util.*; import org.apache.logging.log4j.core.config.*; import org.apache.logging.log4j.core.config.ConfigurationFactory.ConfigurationSource; /** * Lets the base class {@link XMLConfiguration} do all the hard work and patch the object tree before it is being used by {@link BaseConfiguration} * * @author <a href="mailto:alexander.rat...@materna.de">Alexander Rathai</a> */ public class StrictXMLConfiguration extends XMLConfiguration { /** * @param configSource */ public StrictXMLConfiguration(ConfigurationSource configSource) { super(configSource); } /** * @see org.apache.logging.log4j.core.config.XMLConfiguration#setup() */ @Override public void setup() { super.setup(); alterHierarchy(this.rootNode); } /** * Recourses the object tree and puts replaces KeyValuePairs as attributes in the parent object * * @param node the node to alter */ private void alterHierarchy(final Node node) { final List<Node> children = node.getChildren(); // final ArrayList<Node> usedChilds = new ArrayList<>(); Map<String, String> attributes = node.getAttributes(); for( Node child : children ) { if( "KeyValuePair".equalsIgnoreCase(child.getName()) ) { String key = child.getAttributes().get("key"); String value = child.getValue(); attributes.put(key, value); // usedChilds.add(child); } else { alterHierarchy(child); } } // children.removeAll(usedChilds); } } And i patched the xsd a bit: <?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Altered by <a href="mailto:alexander.rat...@materna.de">Alexander Rathai</a>: Tweaked minOccurs maxOccurs and some other things Allowed KeyValuePairType to appear inside AppenderType --> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:element name="Configuration" type="ConfigurationType"/> <xs:complexType name="ConfigurationType"> <xs:sequence> <xs:element name="Properties" type="PropertiesType" minOccurs="0"/> <xs:choice minOccurs="0" maxOccurs="1"> <xs:element name="Filters" type="FiltersType"/> <xs:element name="Filter" type="FilterType"/> </xs:choice> <xs:element name="ThresholdFilter" type="ThresholdFilterType" minOccurs="0"/> <xs:element name="Appenders" type="AppendersType"/> <xs:element name="Loggers" type="LoggersType"/> </xs:sequence> <xs:attribute name="dest" type="xs:string"/> <xs:attribute name="advertiser" type="xs:string"/> <xs:attribute name="monitorInterval" type="xs:int"/> <xs:attribute name="name" type="xs:string"/> <xs:attribute name="packages" type="xs:string"/> <xs:attribute name="schema" type="xs:string"/> <xs:attribute name="shutdownHook" type="xs:boolean"/> <xs:attribute name="status" type="xs:string"/> <xs:attribute name="strict" type="xs:string"/> <xs:attribute name="verbose" type="xs:boolean"/> </xs:complexType> <xs:complexType name="PropertiesType"> <xs:sequence> <xs:element name="Property" type="PropertyType" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="AppenderType"> <xs:sequence> <xs:element name="KeyValuePair" type="KeyValuePairType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="Layout" type="LayoutType" minOccurs="0"/> <xs:choice minOccurs="0" maxOccurs="1"> <xs:element name="Filters" type="FiltersType"/> <xs:element name="Filter" type="FilterType"/> </xs:choice> </xs:sequence> <xs:attribute name="type" type="xs:string" use="required"/> <xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="fileName" type="xs:string" use="optional"/> </xs:complexType> <xs:complexType name="RootType"> <xs:sequence> <xs:element name="AppenderRef" type="AppenderRefType" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="level" type="xs:string"/> </xs:complexType> <xs:complexType name="PropertyType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="name" type="xs:string"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="KeyValuePairType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="key" type="xs:string"/> <xs:attribute name="value" type="xs:string"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="AppendersType"> <xs:sequence> <xs:element name="Appender" type="AppenderType" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="AppenderRefType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="ref" type="xs:string" use="required"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="LoggerType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="1"> <xs:element name="Filters" type="FiltersType"/> <xs:element name="Filter" type="FilterType"/> </xs:choice> <xs:element name="AppenderRef" type="AppenderRefType"/> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="level" type="xs:string" use="optional"/> <xs:attribute name="additivity" type="xs:string" use="optional"/> </xs:complexType> <xs:complexType name="FilterType" mixed="true"> <xs:sequence> <xs:element name="KeyValuePair" type="KeyValuePairType" minOccurs="0"/> </xs:sequence> <xs:attribute name="type" type="xs:string" use="required"/> <xs:attribute name="level" type="xs:string" use="optional"/> <xs:attribute name="marker" type="xs:string" use="optional"/> <xs:attribute name="onMatch" type="xs:string" use="optional"/> <xs:attribute name="onMismatch" type="xs:string" use="optional"/> </xs:complexType> <xs:complexType name="FiltersType"> <xs:sequence> <xs:element name="Filter" type="FilterType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="LoggersType" mixed="true"> <xs:sequence> <xs:element name="Logger" type="LoggerType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="Root" type="RootType" minOccurs="1" maxOccurs="1"/> </xs:sequence> </xs:complexType> <xs:complexType name="LayoutType" mixed="true"> <xs:sequence> <xs:element name="Pattern" type="xs:string" minOccurs="0"/> </xs:sequence> <xs:attribute name="Type" type="xs:string" use="required"/> <xs:attribute name="Pattern" type="xs:string" use="optional"/> </xs:complexType> <xs:complexType name="ThresholdFilterType"> <xs:attribute name="level" type="xs:string" use="optional"/> <xs:attribute name="onMatch" type="xs:string" use="optional"/> <xs:attribute name="onMismatch" type="xs:string" use="optional"/> </xs:complexType> </xs:schema> Then I set the Systemproperty `log4j.configurationFactory` to the fully qualified classname of the StrictXMLConfigurationFactory and it works really well! Best Regards, Alex Alexander Rathai ___________________________________________ MATERNA GmbH Information & Communications Voßkuhle 37 * 44141 Dortmund * Germany Amtsgericht Dortmund * HRB 5839 Geschäftsführer: Dr. Winfried Materna, Helmut an de Meulen, Ralph Hartwig Tel: +49 (231) 5599-8622 http://www.materna.de<http://www.materna.de/>