Externalize examples
diff --git a/pom.xml b/pom.xml
index da15c02..e24b65b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -604,6 +604,23 @@
         </configuration>
       </plugin>
 
+      <!--
+        ~ Adds Antora examples to the list of checked files
+        -->
+      <plugin>
+        <groupId>com.diffplug.spotless</groupId>
+        <artifactId>spotless-maven-plugin</artifactId>
+        <configuration>
+          <java>
+            <includes>
+              <include>src/main/java/**/*.java</include>
+              <include>src/test/java/**/*.java</include>
+              <include>src/site/antora/modules/ROOT/examples/**/*.java</include>
+            </includes>
+          </java>
+        </configuration>
+      </plugin>
+
       <!-- ███████ ████████  █████  ██████  ████████        ███████ ██ ████████ ███████
            ██         ██    ██   ██ ██   ██    ██    ██     ██      ██    ██    ██
            ███████    ██    ███████ ██████     ██           ███████ ██    ██    █████
diff --git a/src/site/antora/antora.tmpl.yml b/src/site/antora/antora.tmpl.yml
index 0b0192a..034e5de 100644
--- a/src/site/antora/antora.tmpl.yml
+++ b/src/site/antora/antora.tmpl.yml
@@ -39,6 +39,7 @@
 asciidoc:
   attributes:
     # Commons
+    antora-examples-url: "https://raw.githubusercontent.com/apache/logging-log4j2/2.x/src/site/antora/modules/ROOT/examples"
     project-github-url: "${scm.url}"
     project-name: "Log4j"
     project-id: "log4j"
diff --git a/src/site/antora/antora.yml b/src/site/antora/antora.yml
index 6e86de6..f5ebbf6 100644
--- a/src/site/antora/antora.yml
+++ b/src/site/antora/antora.yml
@@ -39,7 +39,8 @@
 asciidoc:
   attributes:
     # Commons
-    project-github-url: "https://github.com/apache/logging-log4j2"
+    antora-examples-url: "https://raw.githubusercontent.com/apache/logging-log4j2/2.x/src/site/antora/modules/ROOT/examples"
+    project-github-url: "https://github.com/apache/logging-log4j2/"
     project-name: "Log4j"
     project-id: "log4j"
     java-target-version: "8"
diff --git a/src/site/antora/modules/ROOT/examples/manual/markers/MarkerExample.java b/src/site/antora/modules/ROOT/examples/manual/markers/MarkerExample.java
new file mode 100644
index 0000000..6715c1b
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/markers/MarkerExample.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package example;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.MarkerManager;
+
+public final class MarkerExample {
+
+    private static final Logger logger = LogManager.getLogger("example.MarkerExample");
+    // tag::create-marker[]
+    private static final Marker SQL_MARKER = MarkerManager.getMarker("SQL");
+    // end::create-marker[]
+    // tag::create-marker-parent[]
+    private static final Marker QUERY_MARKER =
+            MarkerManager.getMarker("SQL_QUERY").addParents(SQL_MARKER);
+    private static final Marker UPDATE_MARKER =
+            MarkerManager.getMarker("UPDATE").addParents(SQL_MARKER);
+    // end::create-marker-parent[]
+
+    public static void main(final String[] args) {
+        doQuery("my_table");
+        doQueryParent("my_table");
+        doUpdate("my_table", "column", "value");
+    }
+
+    public static void doQuery(String table) {
+        // Do business logic here
+        // tag::use-marker[]
+        logger.debug(SQL_MARKER, "SELECT * FROM {}", table);
+        // end::use-marker[]
+    }
+
+    public static void doQueryParent(String table) {
+        // Do business logic here
+        // tag::use-marker-parent[]
+        logger.debug(QUERY_MARKER, "SELECT * FROM {}", table);
+        // end::use-marker-parent[]
+    }
+
+    public static void doUpdate(String table, String column, String value) {
+        // Do business logic here
+        // tag::use-marker-parent[]
+        logger.debug(UPDATE_MARKER, "UPDATE {} SET {} = {}", table, column, value);
+        // end::use-marker-parent[]
+    }
+}
diff --git a/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.json b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.json
new file mode 100644
index 0000000..dd79820
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.json
@@ -0,0 +1,31 @@
+{
+  "Configuration": {
+    "Appenders": {
+      "Console": {
+        "name": "SQL_LOG",
+        "PatternLayout": {
+          "pattern": "%d %p %marker - %m%n"
+        }
+      }
+    },
+    "Loggers": {
+      "Root": {
+        "level": "INFO"
+      },
+      // tag::logger[]
+      "Logger": {
+        "name": "example",
+        "level": "ALL", // <1>
+        "AppenderRef": {
+          "ref": "SQL_LOG",
+          "MarkerFilter": { // <2>
+            "marker": "SQL",
+            "onMatch": "ACCEPT",
+            "onMismatch": "DENY"
+          }
+        }
+      }
+      // end::logger[]
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.properties b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.properties
new file mode 100644
index 0000000..e6a8b58
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.properties
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+appender.0.type = Console
+appender.0.name = SQL_LOG
+appender.0.layout.type = PatternLayout
+appender.0.layout.pattern = %d %p %marker - %m%n
+
+rootLogger.level = INFO
+
+# tag::logger[]
+logger.0.name = example
+logger.0.level = ALL # <1>
+logger.0.appenderRef.0.ref = SQL_LOG
+logger.0.appenderRef.0.filter.type = MarkerFilter # <2>
+logger.0.appenderRef.0.filter.marker = SQL
+logger.0.appenderRef.0.filter.onMatch = ACCEPT
+logger.0.appenderRef.0.filter.onMismatch = DENY
+# end::logger[]
diff --git a/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.xml b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.xml
new file mode 100644
index 0000000..7127c7c
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.xml
@@ -0,0 +1,39 @@
+<?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.
+  -->
+<Configuration xmlns="https://logging.apache.org/xml/ns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xsi:schemaLocation="
+                   https://logging.apache.org/xml/ns
+                   https://logging.apache.org/xml/ns/log4j-config-2.xsd">
+  <Appenders>
+    <Console name="SQL_LOG">
+      <PatternLayout pattern="%d %p %-32marker - %m%n"/>
+    </Console>
+  </Appenders>
+  <Loggers>
+    <Root level="INFO"/>
+    <!-- tag::logger[] -->
+    <Logger name="example" level="ALL"><!--1-->
+      <AppenderRef ref="SQL_LOG">
+        <MarkerFilter marker="SQL"
+                      onMatch="ACCEPT"
+                      onMismatch="DENY"/><!--2-->
+      </AppenderRef>
+    </Logger>
+    <!-- end::logger[] -->
+  </Loggers>
+</Configuration>
diff --git a/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.yaml b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.yaml
new file mode 100644
index 0000000..d742eaf
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.yaml
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+Configuration:
+  Appenders:
+    Console:
+      name: "SQL_LOG"
+      PatternLayout:
+        pattern: "%d %p %marker - %m%n"
+  Loggers:
+    Root:
+      level: "INFO"
+    # tag::logger[]
+    Logger:
+      name: "example"
+      level: "ALL" # <1>
+      AppenderRef:
+        ref: "SQL_LOG"
+        MarkerFilter: # <2>
+          marker: "SQL"
+          onMatch: "ACCEPT"
+          onMismatch: DENY
+    # end::logger[]
diff --git a/src/site/antora/modules/ROOT/examples/manual/markers/marker-filtering.log b/src/site/antora/modules/ROOT/examples/manual/markers/marker-filtering.log
new file mode 100644
index 0000000..cfbc745
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/markers/marker-filtering.log
@@ -0,0 +1,7 @@
+# tag::use-marker[]
+{docdate} 10:42:30,982 DEBUG [ SQL ] - SELECT * FROM my_table
+# end::use-marker[]
+# tag::use-marker-parent[]
+{docdate} 10:42:30,982 DEBUG [ SQL_QUERY[ SQL ] ] - SELECT * FROM my_table
+{docdate} 10:42:30,982 DEBUG [ SQL_UPDATE[ SQL ] ] - UPDATE my_table SET column = value
+# end::use-marker-parent[]
\ No newline at end of file
diff --git a/src/site/antora/modules/ROOT/pages/manual/markers.adoc b/src/site/antora/modules/ROOT/pages/manual/markers.adoc
index be12bda..29ca8f5 100644
--- a/src/site/antora/modules/ROOT/pages/manual/markers.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/markers.adoc
@@ -16,9 +16,9 @@
 ////
 = Markers
 
-Markers allow "tag" log statements with a
+Markers allow to "tag" log statements with a
 link:../javadoc/log4j-api/org/apache/logging/log4j/Marker.html[`Marker`]
-object, labeling them as belonging to a specific type. 
+object, labeling them as belonging to a specific type.
 For example, developers can use markers to tag log statements related to a particular subsystem or functionality.
 
 By using markers, it is possible to filter log statements based on the `Marker`
@@ -30,106 +30,129 @@
 [#create]
 == Creating Markers
 
-To create a `Marker`, use the `MarkerManager` class as follows:
+[#simple-markers]
+=== Simple markers
 
-[source, java]
+To create a `Marker`, create a field in your class using the `MarkerManager.getMarker()` method:
+
+[source,java,indent=0]
 ----
-Marker SQL_MARKER = MarkerManager.getMarker("SQL");
+include::example$manual/markers/MarkerExample.java[tag=create-marker]
 ----
 
 Since a `Marker` is reusable across multiple log statements, storing it in a `static final` field makes it a constant.
 Once created, use it as the first argument in the log statement:
 
-[source, java]
+[source,java,indent=0]
 ----
-LOGGER.debug(SQL_MARKER, "Here is my SQL related message");
+include::example$manual/markers/MarkerExample.java[tag=use-marker]
 ----
 
-The example below creates the marker as the constant and then uses it to tag a log statement.
-The log method works _as usual_, but the marker needs to be the first argument.
+If you use the <<example-configuration,configuration example below>>, you'll see the following log statement on your console:
 
-[source, java]
+[subs=+attributes]
 ----
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.MarkerManager;
-
-public class MyApp {
-
-    private static final Logger LOGGER = LogManager.getLogger();
-
-    private static final Marker SQL_MARKER = MarkerManager.getMarker("MY_APP_SQL"); <1>
-
-    public void doQuery(String table) {
-        // Do business logic here        
-
-        LOGGER.debug(SQL_MARKER, "SELECT * FROM {}", table); <2>
-    }
-}
+include::example$manual/markers/marker-filtering.log[tag=use-marker]
 ----
-<1> The marker is created and stored as a constant
-<2> Using the marker to tag a log statement
-
-You must create a configuration file to write log statements tagged with the "SQL" marker to the console. 
-This file uses the `<MarkerFilter>` element to accept or deny log statements 
-based on the marker. 
-
-The following code shows how the `MarkerFilter` is used in the configuration file. 
-It assumes that the `Console` appender is defined in the configuration file.
-
-Once a developer tags a log event with a marker, we can apply specialized configuration on that particular marker.
-For instance, we can use a xref:manual/filters.adoc#MarkerFilter[`MarkerFilter`] to redirect 
-log events whose marker matches a particular name to a dedicated appender.
-In the example below, Log4j redirects all `MY_SQL_APP`-marked log messages from the `com.example` package to the `CONSOLE` appender:
-
-[source, xml]
-----
-<logger name="com.example" level="OFF"><!--1-->
-  <AppenderRef ref="CONSOLE">
-    <Filters>
-      <MarkerFilter marker="MY_APP_SQL" onMatch="ACCEPT" onMismatch="DENY"/><!--2-->
-    </Filters>
-  </AppenderRef>
-</logger>
-----
-<1> Match all messages from `com.example` package from all levels
-<2> Only allow `MY_APP_SQL`-marked messages
 
 [#hierarchy]
-== Parent and child markers
+=== Parent and child markers
 
 A marker can have zero or more parent markers, allowing for a hierarchy of markers.
-To create such a hierarchy, you must use the `setParents` method on the `Marker` object
-after you create the child marker. This method will connect both markers.
+To create such a hierarchy, you must use the `addParents()` method on the `Marker` object after you create the child marker.
 
-[source, java]
+[source,java,indent=0]
 ----
-Marker SQL_MARKER = MarkerManager.getMarker("MY_APP_SQL"); // <1>
-Marker UPDATE_MARKER = MarkerManager.getMarker("MY_APP_SQL_UPDATE").setParents(SQL_MARKER); // <2>
-----
-<1> Creating the parent marker
-<2> Creating the child marker and connecting it to the parent marker
-
-The child marker works as expected by adding to the log method as the first argument.
-
-[source, java]
-----
-LOGGER.debug(UPDATE_MARKER, "UPDATE {} SET {}", table, values);
+include::example$manual/markers/MarkerExample.java[tag=create-marker-parent]
 ----
 
-It is now possible to filter for the parent or, more specifically, only for the child marker.
+The usage of child markers does not differ from the usage of simple markers, you just need to pass them as the first argument of a logging call.
+
+[source,java,indent=0]
+----
+include::example$manual/markers/MarkerExample.java[tag=use-marker-parent]
+----
+
+Messages marked with children markers behave as if they were both marked with the children marker and all its parents.
+If you use the <<example-configuration,configuration example below>>, you'll see the following log statement on your console:
+
+[subs=+attributes]
+----
+include::example$manual/markers/marker-filtering.log[tag=use-marker-parent]
+----
+
+[#configuring-log4j]
+== Configuring filtering
+
+Markers can be used to filter the log statements that are delivered to your log files.
+Marker processing is supported at least by
+https://logback.qos.ch/manual/filters.html#TurboFilter[Logback]
+and the Log4j Core logging backends.
+Will will discuss only the configuration of the latter.
+
+In order to filter messages by marker, you need to add
+xref:manual/filters.adoc#MarkerFilter[`MarkerFilter`]
+to your configuration file.
+For example the snippet below can be used to redirect all SQL-related logs to the `SQL_LOG` appender:
+
+[[example-configuration]]
+[tabs]
+====
+XML::
++
+[source,xml]
+----
+include::example$manual/markers/log4j2.xml[tag=logger]
+----
+
+JSON::
++
+[source,json]
+----
+include::example$manual/markers/log4j2.json[tag=logger]
+----
+
+YAML::
++
+[source,yaml]
+----
+include::example$manual/markers/log4j2.yaml[tag=logger]
+----
+
+Java properties::
++
+[source,properties]
+----
+include::example$manual/markers/log4j2.properties[tag=logger]
+----
+====
+
+<1> Match all messages from `example` package from all levels
+<2> Only allow messages marker with `SQL` or one of its children to be sent to the `SQL_LOG` appender.
 
 [#pitfalls]
 == Pitfalls
 
-It is important to note that marker names must be unique, as Log4j registers them permanently by name. 
-Developers should avoid generic marker names, as they may conflict with 
+It is important to note that marker names must be unique, as Log4j registers them permanently by name.
+Developers should avoid generic marker names, as they may conflict with
 those provided by third parties. Except, of course, if the user is aware of the implications.
 
-While it is possible to add or remove parent markers dynamically through the `setParents()' method, 
-it is generally advisable to set the parents when the marker is created. 
+While it is possible to add or remove parent markers dynamically through the `setParents()' method,
+it is generally advisable to set the parents when the marker is created.
 This is for efficiency and performance reasons.
 
-It is also worth noting that markers without parents are more efficient to evaluate 
-than markers with multiple parents. It is generally a good idea to avoid 
+It is also worth noting that markers without parents are more efficient to evaluate
+than markers with multiple parents. It is generally a good idea to avoid
 complex hierarchies of markers where possible.
+
+[#complete-example]
+== Complete example
+
+To try the examples on this page:
+
+* add
+{antora-examples-url}/manual/markers/MarkerExample.java[MarkerExample.java]
+to the `src/main/java/example` folder of your project,
+* add
+{antora-examples-url}/manual/markers/log4j2.xml[log4j2.xml]
+to the `src/main/resources` folder of your project.