You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2022/03/27 02:51:50 UTC

[logging-log4j2] branch master updated (9e6961e -> e8fdd73)

This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git.


    from 9e6961e  LOG4J2-3449 - Disable flaky rolling tests
     new 455457f  Disable compiler forking
     new 088f15f  Remove unused imports
     new e8fdd73  Make TypeConverter plugins injectable

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../logging/log4j/cassandra/CassandraManager.java  |  16 +-
 .../config/plugins/convert/TypeConvertersTest.java |  28 +--
 .../plugins/convert/CoreTypeConvertersTest.java    |  25 ++-
 .../log4j/core/appender/db/ColumnMapping.java      |  24 ++-
 .../config/plugins/convert/CoreTypeConverters.java |  37 ++--
 .../plugins/visit/PluginAttributeVisitor.java      |  18 +-
 .../visit/PluginBuilderAttributeVisitor.java       |   7 +-
 .../logging/log4j/couchdb/CouchDbProvider.java     |  14 +-
 .../log4j/jdbc/appender/JdbcDatabaseManager.java   |  40 ++--
 .../template/json/util/RecyclerFactories.java      |   3 -
 .../json/util/RecyclerFactoryConverter.java        |   3 +-
 .../template/json/util/RecyclerFactoriesTest.java  |  13 +-
 .../logging/log4j/mongodb3/MongoDb3Provider.java   |  33 ++--
 .../plugins/convert/TypeConverterRegistryTest.java |  22 ++-
 .../log4j/plugins/convert/TypeConverter.java       |  38 +++-
 .../plugins/convert/TypeConverterRegistry.java     | 210 ---------------------
 .../log4j/plugins/convert/TypeConverters.java      |  96 ----------
 .../logging/log4j/plugins/di/DefaultInjector.java  | 128 +++++++++++++
 .../apache/logging/log4j/plugins/di/Injector.java  |  11 ++
 .../validation/validators/ValidPortValidator.java  |  15 +-
 .../plugins/visit/PluginAttributeVisitor.java      |  18 +-
 .../visit/PluginBuilderAttributeVisitor.java       |  15 +-
 pom.xml                                            |   2 +-
 .../asciidoc/manual/json-template-layout.adoc.vm   |   3 +-
 24 files changed, 381 insertions(+), 438 deletions(-)
 delete mode 100644 log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverterRegistry.java
 delete mode 100644 log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverters.java

[logging-log4j2] 03/03: Make TypeConverter plugins injectable

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit e8fdd738da0e7f67dbb04c4baaa400aa4ca7c0c2
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sat Mar 26 21:51:29 2022 -0500

    Make TypeConverter plugins injectable
    
    This adds Injector::getTypeConverter to replace some old utility classes for holding static state.
    
    Signed-off-by: Matt Sicker <ma...@apache.org>
---
 .../logging/log4j/cassandra/CassandraManager.java  |  16 +-
 .../config/plugins/convert/TypeConvertersTest.java |  28 +--
 .../plugins/convert/CoreTypeConvertersTest.java    |  25 ++-
 .../log4j/core/appender/db/ColumnMapping.java      |  24 ++-
 .../config/plugins/convert/CoreTypeConverters.java |  37 ++--
 .../plugins/visit/PluginAttributeVisitor.java      |  18 +-
 .../visit/PluginBuilderAttributeVisitor.java       |   7 +-
 .../logging/log4j/couchdb/CouchDbProvider.java     |  14 +-
 .../log4j/jdbc/appender/JdbcDatabaseManager.java   |  40 ++--
 .../json/util/RecyclerFactoryConverter.java        |   3 +-
 .../template/json/util/RecyclerFactoriesTest.java  |  13 +-
 .../logging/log4j/mongodb3/MongoDb3Provider.java   |  33 ++--
 .../plugins/convert/TypeConverterRegistryTest.java |  22 ++-
 .../log4j/plugins/convert/TypeConverter.java       |  38 +++-
 .../plugins/convert/TypeConverterRegistry.java     | 210 ---------------------
 .../log4j/plugins/convert/TypeConverters.java      |  96 ----------
 .../logging/log4j/plugins/di/DefaultInjector.java  | 128 +++++++++++++
 .../apache/logging/log4j/plugins/di/Injector.java  |  11 ++
 .../validation/validators/ValidPortValidator.java  |  15 +-
 .../plugins/visit/PluginAttributeVisitor.java      |  18 +-
 .../visit/PluginBuilderAttributeVisitor.java       |  15 +-
 .../asciidoc/manual/json-template-layout.adoc.vm   |   3 +-
 22 files changed, 380 insertions(+), 434 deletions(-)

diff --git a/log4j-cassandra/src/main/java/org/apache/logging/log4j/cassandra/CassandraManager.java b/log4j-cassandra/src/main/java/org/apache/logging/log4j/cassandra/CassandraManager.java
index 7ae8393..88f87d7 100644
--- a/log4j-cassandra/src/main/java/org/apache/logging/log4j/cassandra/CassandraManager.java
+++ b/log4j-cassandra/src/main/java/org/apache/logging/log4j/cassandra/CassandraManager.java
@@ -16,12 +16,6 @@
  */
 package org.apache.logging.log4j.cassandra;
 
-import java.io.Serializable;
-import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
 import com.datastax.driver.core.BatchStatement;
 import com.datastax.driver.core.BoundStatement;
 import com.datastax.driver.core.Cluster;
@@ -31,7 +25,6 @@ import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.appender.ManagerFactory;
 import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
 import org.apache.logging.log4j.core.appender.db.ColumnMapping;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
 import org.apache.logging.log4j.core.net.SocketAddress;
 import org.apache.logging.log4j.jdbc.convert.DateTypeConverter;
 import org.apache.logging.log4j.spi.ThreadContextMap;
@@ -39,6 +32,12 @@ import org.apache.logging.log4j.spi.ThreadContextStack;
 import org.apache.logging.log4j.util.ReadOnlyStringMap;
 import org.apache.logging.log4j.util.Strings;
 
+import java.io.Serializable;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
 /**
  * Manager for a Cassandra appender instance.
  */
@@ -99,8 +98,7 @@ public class CassandraManager extends AbstractDatabaseManager {
             } else if (Date.class.isAssignableFrom(columnMapping.getType())) {
                 values[i] = DateTypeConverter.fromMillis(event.getTimeMillis(), columnMapping.getType().asSubclass(Date.class));
             } else {
-                values[i] = TypeConverters.convert(columnMapping.getLayout().toSerializable(event),
-                    columnMapping.getType(), null);
+                values[i] = columnMapping.getTypeConverter().convert(columnMapping.getLayout().toSerializable(event), null);
             }
         }
         final BoundStatement boundStatement = preparedStatement.bind(values);
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/convert/TypeConvertersTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/convert/TypeConvertersTest.java
index 6e5e62f..0416d32 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/convert/TypeConvertersTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/plugins/convert/TypeConvertersTest.java
@@ -17,6 +17,17 @@
 
 package org.apache.logging.log4j.core.config.plugins.convert;
 
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.appender.rolling.action.Duration;
+import org.apache.logging.log4j.core.layout.GelfLayout;
+import org.apache.logging.log4j.core.net.Facility;
+import org.apache.logging.log4j.plugins.di.DI;
+import org.apache.logging.log4j.plugins.di.Injector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
 import java.io.File;
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -33,17 +44,8 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.UUID;
 
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.core.Filter;
-import org.apache.logging.log4j.core.appender.rolling.action.Duration;
-import org.apache.logging.log4j.core.layout.GelfLayout;
-import org.apache.logging.log4j.core.net.Facility;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
 
 /**
  * Tests {@link CoreTypeConverters}.
@@ -216,7 +218,9 @@ public class TypeConvertersTest {
 
     @Test
     public void testConvert() throws Exception {
-        final Object actual = TypeConverters.convert(value, clazz, defaultValue);
+        final Injector injector = DI.createInjector();
+        injector.init();
+        final Object actual = injector.getTypeConverter(clazz).convert(value, defaultValue);
         final String assertionMessage = "\nGiven: " + value + "\nDefault: " + defaultValue;
         if (expected != null && expected instanceof char[]) {
             assertArrayEquals(assertionMessage, (char[]) expected, (char[]) actual);
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/plugins/convert/CoreTypeConvertersTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/plugins/convert/CoreTypeConvertersTest.java
index 117ceea..1f13210 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/plugins/convert/CoreTypeConvertersTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/plugins/convert/CoreTypeConvertersTest.java
@@ -17,29 +17,37 @@
 package org.apache.logging.log4j.core.plugins.convert;
 
 import org.apache.logging.log4j.plugins.convert.TypeConverter;
-import org.apache.logging.log4j.plugins.convert.TypeConverterRegistry;
+import org.apache.logging.log4j.plugins.di.DI;
+import org.apache.logging.log4j.plugins.di.Injector;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.*;
 
 public class CoreTypeConvertersTest {
 
+    private final Injector injector = DI.createInjector();
+
+    @BeforeEach
+    void setUp() {
+        injector.init();
+    }
+
     @Test
     public void testFindNullConverter() {
-        assertThrows(NullPointerException.class,
-                () -> TypeConverterRegistry.getInstance().findCompatibleConverter(null));
+        assertThrows(NullPointerException.class, () -> injector.getTypeConverter(null));
     }
 
     @Test
     public void testFindBooleanConverter() throws Exception {
-        final TypeConverter<?> converter = TypeConverterRegistry.getInstance().findCompatibleConverter(Boolean.class);
+        final TypeConverter<?> converter = injector.getTypeConverter(Boolean.class);
         assertNotNull(converter);
         assertTrue((Boolean) converter.convert("TRUE"));
     }
 
     @Test
     public void testFindPrimitiveBooleanConverter() throws Exception {
-        final TypeConverter<?> converter = TypeConverterRegistry.getInstance().findCompatibleConverter(Boolean.TYPE);
+        final TypeConverter<?> converter = injector.getTypeConverter(Boolean.TYPE);
         assertNotNull(converter);
         assertTrue((Boolean) converter.convert("tRUe"));
     }
@@ -48,7 +56,7 @@ public class CoreTypeConvertersTest {
     @Test
     public void testFindCharSequenceConverterUsingStringConverter() throws Exception {
         final TypeConverter<CharSequence> converter = (TypeConverter<CharSequence>)
-            TypeConverterRegistry.getInstance().findCompatibleConverter(CharSequence.class);
+                injector.getTypeConverter(CharSequence.class);
         assertNotNull(converter);
         final CharSequence expected = "This is a test sequence of characters";
         final CharSequence actual = converter.convert(expected.toString());
@@ -59,7 +67,7 @@ public class CoreTypeConvertersTest {
     @Test
     public void testFindNumberConverter() throws Exception {
         final TypeConverter<Number> numberTypeConverter = (TypeConverter<Number>)
-            TypeConverterRegistry.getInstance().findCompatibleConverter(Number.class);
+                injector.getTypeConverter(Number.class);
         assertNotNull(numberTypeConverter);
         // TODO: is there a specific converter this should return?
     }
@@ -71,8 +79,7 @@ public class CoreTypeConvertersTest {
     @SuppressWarnings("unchecked")
     @Test
     public void testFindEnumConverter() throws Exception {
-        final TypeConverter<Foo> fooTypeConverter = (TypeConverter<Foo>)
-            TypeConverterRegistry.getInstance().findCompatibleConverter(Foo.class);
+        final TypeConverter<Foo> fooTypeConverter = (TypeConverter<Foo>) injector.getTypeConverter(Foo.class);
         assertNotNull(fooTypeConverter);
         assertEquals(Foo.I, fooTypeConverter.convert("i"));
         assertEquals(Foo.PITY, fooTypeConverter.convert("pity"));
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/ColumnMapping.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/ColumnMapping.java
index 740ebc8..a58e4e2 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/ColumnMapping.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/ColumnMapping.java
@@ -22,10 +22,13 @@ import org.apache.logging.log4j.core.StringLayout;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
 import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.plugins.Inject;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginBuilderAttribute;
 import org.apache.logging.log4j.plugins.PluginElement;
 import org.apache.logging.log4j.plugins.PluginFactory;
+import org.apache.logging.log4j.plugins.convert.TypeConverter;
+import org.apache.logging.log4j.plugins.di.Injector;
 import org.apache.logging.log4j.plugins.validation.constraints.Required;
 import org.apache.logging.log4j.spi.ThreadContextMap;
 import org.apache.logging.log4j.spi.ThreadContextStack;
@@ -34,6 +37,7 @@ import org.apache.logging.log4j.util.ReadOnlyStringMap;
 
 import java.util.Date;
 import java.util.Locale;
+import java.util.function.Supplier;
 
 /**
  * A configuration element for specifying a database column name mapping.
@@ -74,6 +78,8 @@ public class ColumnMapping {
         @Required(message = "No conversion type provided")
         private Class<?> type = String.class;
 
+        private Injector injector;
+
         @Override
         public ColumnMapping build() {
             if (pattern != null) {
@@ -96,7 +102,7 @@ public class ColumnMapping {
                 LOGGER.error("Only one of 'literal' or 'parameter' can be set on the column mapping {}", this);
                 return null;
             }
-            return new ColumnMapping(name, source, layout, literal, parameter, type);
+            return new ColumnMapping(name, source, layout, literal, parameter, type, () -> injector.getTypeConverter(type));
         }
 
         public Builder setConfiguration(final Configuration configuration) {
@@ -181,6 +187,12 @@ public class ColumnMapping {
             return this;
         }
 
+        @Inject
+        public Builder setInjector(final Injector injector) {
+            this.injector = injector;
+            return this;
+        }
+
         @Override
         public String toString() {
             return "Builder [name=" + name + ", source=" + source + ", literal=" + literal + ", parameter=" + parameter
@@ -206,8 +218,11 @@ public class ColumnMapping {
     private final String parameter;
     private final String source;
     private final Class<?> type;
+    private final Supplier<TypeConverter<?>> typeConverter;
 
-    private ColumnMapping(final String name, final String source, final StringLayout layout, final String literalValue, final String parameter, final Class<?> type) {
+    private ColumnMapping(
+            final String name, final String source, final StringLayout layout, final String literalValue,
+            final String parameter, final Class<?> type, final Supplier<TypeConverter<?>> typeConverter) {
         this.name = name;
         this.nameKey = toKey(name);
         this.source = source;
@@ -215,6 +230,7 @@ public class ColumnMapping {
         this.literalValue = literalValue;
         this.parameter = parameter;
         this.type = type;
+        this.typeConverter = typeConverter;
     }
 
     public StringLayout getLayout() {
@@ -245,6 +261,10 @@ public class ColumnMapping {
         return type;
     }
 
+    public TypeConverter<?> getTypeConverter() {
+        return typeConverter.get();
+    }
+
     @Override
     public String toString() {
         return "ColumnMapping [name=" + name + ", source=" + source + ", literalValue=" + literalValue + ", parameter="
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/convert/CoreTypeConverters.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/convert/CoreTypeConverters.java
index 352f347..dcf1804 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/convert/CoreTypeConverters.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/convert/CoreTypeConverters.java
@@ -22,7 +22,6 @@ import org.apache.logging.log4j.core.appender.rolling.action.Duration;
 import org.apache.logging.log4j.core.util.CronExpression;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.convert.TypeConverter;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
 import org.apache.logging.log4j.util.LoaderUtil;
 
 import java.io.File;
@@ -55,7 +54,7 @@ public final class CoreTypeConverters {
     /**
      * Parses a {@link String} into a {@link BigDecimal}.
      */
-    @Plugin(name = "BigDecimal", category = TypeConverters.CATEGORY)
+    @Plugin(name = "BigDecimal", category = TypeConverter.CATEGORY)
     public static class BigDecimalConverter implements TypeConverter<BigDecimal> {
         @Override
         public BigDecimal convert(final String s) {
@@ -66,7 +65,7 @@ public final class CoreTypeConverters {
     /**
      * Parses a {@link String} into a {@link BigInteger}.
      */
-    @Plugin(name = "BigInteger", category = TypeConverters.CATEGORY)
+    @Plugin(name = "BigInteger", category = TypeConverter.CATEGORY)
     public static class BigIntegerConverter implements TypeConverter<BigInteger> {
         @Override
         public BigInteger convert(final String s) {
@@ -84,7 +83,7 @@ public final class CoreTypeConverters {
      * <li>String using {@link Charset#defaultCharset()} [TODO Should this be UTF-8 instead?]</li>
      * </ul>
      */
-    @Plugin(name = "ByteArray", category = TypeConverters.CATEGORY)
+    @Plugin(name = "ByteArray", category = TypeConverter.CATEGORY)
     public static class ByteArrayConverter implements TypeConverter<byte[]> {
 
         private static final String PREFIX_0x = "0x";
@@ -111,7 +110,7 @@ public final class CoreTypeConverters {
     /**
      * Converts a {@link String} into a {@code char[]}.
      */
-    @Plugin(name = "CharacterArray", category = TypeConverters.CATEGORY)
+    @Plugin(name = "CharacterArray", category = TypeConverter.CATEGORY)
     public static class CharArrayConverter implements TypeConverter<char[]> {
         @Override
         public char[] convert(final String s) {
@@ -122,7 +121,7 @@ public final class CoreTypeConverters {
     /**
      * Converts a {@link String} into a {@link Charset}.
      */
-    @Plugin(name = "Charset", category = TypeConverters.CATEGORY)
+    @Plugin(name = "Charset", category = TypeConverter.CATEGORY)
     public static class CharsetConverter implements TypeConverter<Charset> {
         @Override
         public Charset convert(final String s) {
@@ -133,7 +132,7 @@ public final class CoreTypeConverters {
     /**
      * Converts a {@link String} into a {@link Class}.
      */
-    @Plugin(name = "Class", category = TypeConverters.CATEGORY)
+    @Plugin(name = "Class", category = TypeConverter.CATEGORY)
     public static class ClassConverter implements TypeConverter<Class<?>> {
         @Override
         public Class<?> convert(final String s) throws ClassNotFoundException {
@@ -163,7 +162,7 @@ public final class CoreTypeConverters {
         }
     }
 
-    @Plugin(name = "CronExpression", category = TypeConverters.CATEGORY)
+    @Plugin(name = "CronExpression", category = TypeConverter.CATEGORY)
     public static class CronExpressionConverter implements TypeConverter<CronExpression> {
         @Override
         public CronExpression convert(final String s) throws Exception {
@@ -175,7 +174,7 @@ public final class CoreTypeConverters {
      * Converts a {@link String} into a {@link Duration}.
      * @since 2.5
      */
-    @Plugin(name = "Duration", category = TypeConverters.CATEGORY)
+    @Plugin(name = "Duration", category = TypeConverter.CATEGORY)
     public static class DurationConverter implements TypeConverter<Duration> {
         @Override
         public Duration convert(final String s) {
@@ -186,7 +185,7 @@ public final class CoreTypeConverters {
     /**
      * Converts a {@link String} into a {@link File}.
      */
-    @Plugin(name = "File", category = TypeConverters.CATEGORY)
+    @Plugin(name = "File", category = TypeConverter.CATEGORY)
     public static class FileConverter implements TypeConverter<File> {
         @Override
         public File convert(final String s) {
@@ -197,7 +196,7 @@ public final class CoreTypeConverters {
     /**
      * Converts a {@link String} into an {@link InetAddress}.
      */
-    @Plugin(name = "InetAddress", category = TypeConverters.CATEGORY)
+    @Plugin(name = "InetAddress", category = TypeConverter.CATEGORY)
     public static class InetAddressConverter implements TypeConverter<InetAddress> {
         @Override
         public InetAddress convert(final String s) throws Exception {
@@ -208,7 +207,7 @@ public final class CoreTypeConverters {
     /**
      * Converts a {@link String} into a Log4j {@link Level}. Returns {@code null} for invalid level names.
      */
-    @Plugin(name = "Level", category = TypeConverters.CATEGORY)
+    @Plugin(name = "Level", category = TypeConverter.CATEGORY)
     public static class LevelConverter implements TypeConverter<Level> {
         @Override
         public Level convert(final String s) {
@@ -220,7 +219,7 @@ public final class CoreTypeConverters {
      * Converts a {@link String} into a {@link Path}.
      * @since 2.8
      */
-    @Plugin(name = "Path", category = TypeConverters.CATEGORY)
+    @Plugin(name = "Path", category = TypeConverter.CATEGORY)
     public static class PathConverter implements TypeConverter<Path> {
         @Override
         public Path convert(final String s) throws Exception {
@@ -231,7 +230,7 @@ public final class CoreTypeConverters {
     /**
      * Converts a {@link String} into a {@link Pattern}.
      */
-    @Plugin(name = "Pattern", category = TypeConverters.CATEGORY)
+    @Plugin(name = "Pattern", category = TypeConverter.CATEGORY)
     public static class PatternConverter implements TypeConverter<Pattern> {
         @Override
         public Pattern convert(final String s) {
@@ -242,7 +241,7 @@ public final class CoreTypeConverters {
     /**
      * Converts a {@link String} into a {@link Provider}.
      */
-    @Plugin(name = "SecurityProvider", category = TypeConverters.CATEGORY)
+    @Plugin(name = "SecurityProvider", category = TypeConverter.CATEGORY)
     public static class SecurityProviderConverter implements TypeConverter<Provider> {
         @Override
         public Provider convert(final String s) {
@@ -253,7 +252,7 @@ public final class CoreTypeConverters {
     /**
      * Converts a {@link String} into a {@link URI}.
      */
-    @Plugin(name = "URI", category = TypeConverters.CATEGORY)
+    @Plugin(name = "URI", category = TypeConverter.CATEGORY)
     public static class UriConverter implements TypeConverter<URI> {
         @Override
         public URI convert(final String s) throws URISyntaxException {
@@ -264,7 +263,7 @@ public final class CoreTypeConverters {
     /**
      * Converts a {@link String} into a {@link URL}.
      */
-    @Plugin(name = "URL", category = TypeConverters.CATEGORY)
+    @Plugin(name = "URL", category = TypeConverter.CATEGORY)
     public static class UrlConverter implements TypeConverter<URL> {
         @Override
         public URL convert(final String s) throws MalformedURLException {
@@ -276,7 +275,7 @@ public final class CoreTypeConverters {
      * Converts a {@link String} into a {@link UUID}.
      * @since 2.8
      */
-    @Plugin(name = "UUID", category = TypeConverters.CATEGORY)
+    @Plugin(name = "UUID", category = TypeConverter.CATEGORY)
     public static class UuidConverter implements TypeConverter<UUID> {
         @Override
         public UUID convert(final String s) throws Exception {
@@ -284,7 +283,7 @@ public final class CoreTypeConverters {
         }
     }
 
-    @Plugin(name = "ZoneId", category = TypeConverters.CATEGORY)
+    @Plugin(name = "ZoneId", category = TypeConverter.CATEGORY)
     public static class ZoneIdConverter implements TypeConverter<ZoneId> {
         @Override
         public ZoneId convert(final String s) throws Exception {
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visit/PluginAttributeVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visit/PluginAttributeVisitor.java
index 798a400..4e138a8 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visit/PluginAttributeVisitor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visit/PluginAttributeVisitor.java
@@ -21,7 +21,8 @@ import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
 import org.apache.logging.log4j.plugins.Inject;
 import org.apache.logging.log4j.plugins.Named;
 import org.apache.logging.log4j.plugins.Node;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
+import org.apache.logging.log4j.plugins.convert.TypeConverter;
+import org.apache.logging.log4j.plugins.di.Injector;
 import org.apache.logging.log4j.plugins.di.Keys;
 import org.apache.logging.log4j.plugins.name.AnnotatedElementAliasesProvider;
 import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
@@ -60,10 +61,14 @@ public class PluginAttributeVisitor implements NodeVisitor {
     );
 
     private final Function<String, String> stringSubstitutionStrategy;
+    private final Injector injector;
 
     @Inject
-    public PluginAttributeVisitor(@Named(Keys.SUBSTITUTOR_NAME) final Function<String, String> stringSubstitutionStrategy) {
+    public PluginAttributeVisitor(
+            @Named(Keys.SUBSTITUTOR_NAME) final Function<String, String> stringSubstitutionStrategy,
+            final Injector injector) {
         this.stringSubstitutionStrategy = stringSubstitutionStrategy;
+        this.injector = injector;
     }
 
     @Override
@@ -71,10 +76,11 @@ public class PluginAttributeVisitor implements NodeVisitor {
         final String name = AnnotatedElementNameProvider.getName(field);
         final Collection<String> aliases = AnnotatedElementAliasesProvider.getAliases(field);
         final Type targetType = field.getGenericType();
+        final TypeConverter<?> converter = injector.getTypeConverter(targetType);
         final PluginAttribute annotation = field.getAnnotation(PluginAttribute.class);
         final boolean sensitive = annotation.sensitive();
         final Object value = node.removeMatchingAttribute(name, aliases)
-                .map(stringSubstitutionStrategy.andThen(s -> TypeConverters.convert(s, targetType, null, sensitive)))
+                .map(stringSubstitutionStrategy.andThen(s -> (Object) converter.convert(s, null, sensitive)))
                 .orElseGet(() -> getDefaultValue(targetType, annotation));
         StringBuilders.appendKeyDqValueWithJoiner(debugLog, name, sensitive ? "(***)" : value, ", ");
         return value;
@@ -85,10 +91,11 @@ public class PluginAttributeVisitor implements NodeVisitor {
         final String name = AnnotatedElementNameProvider.getName(parameter);
         final Collection<String> aliases = AnnotatedElementAliasesProvider.getAliases(parameter);
         final Type targetType = parameter.getParameterizedType();
+        final TypeConverter<?> converter = injector.getTypeConverter(targetType);
         final PluginAttribute annotation = parameter.getAnnotation(PluginAttribute.class);
         final boolean sensitive = annotation.sensitive();
         final Object value = node.removeMatchingAttribute(name, aliases)
-                .map(stringSubstitutionStrategy.andThen(s -> TypeConverters.convert(s, targetType, null, sensitive)))
+                .map(stringSubstitutionStrategy.andThen(s -> (Object) converter.convert(s, null, sensitive)))
                 .orElseGet(() -> getDefaultValue(targetType, annotation));
         StringBuilders.appendKeyDqValueWithJoiner(debugLog, name, sensitive ? "(***)" : value, ", ");
         return value;
@@ -99,7 +106,8 @@ public class PluginAttributeVisitor implements NodeVisitor {
         if (extractor != null) {
             return extractor.apply(annotation);
         }
+        final TypeConverter<?> converter = injector.getTypeConverter(targetType);
         final var value = stringSubstitutionStrategy.apply(annotation.defaultString());
-        return Strings.isEmpty(value) ? null : TypeConverters.convert(value, targetType, null, false);
+        return Strings.isEmpty(value) ? null : converter.convert(value, null);
     }
 }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visit/PluginBuilderAttributeVisitor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visit/PluginBuilderAttributeVisitor.java
index 9d6fe54..658b5f1 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visit/PluginBuilderAttributeVisitor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/plugins/visit/PluginBuilderAttributeVisitor.java
@@ -20,6 +20,7 @@ package org.apache.logging.log4j.core.config.plugins.visit;
 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
 import org.apache.logging.log4j.plugins.Inject;
 import org.apache.logging.log4j.plugins.Named;
+import org.apache.logging.log4j.plugins.di.Injector;
 import org.apache.logging.log4j.plugins.di.Keys;
 
 import java.lang.reflect.AnnotatedElement;
@@ -27,8 +28,10 @@ import java.util.function.Function;
 
 public class PluginBuilderAttributeVisitor extends org.apache.logging.log4j.plugins.visit.PluginBuilderAttributeVisitor {
     @Inject
-    public PluginBuilderAttributeVisitor(@Named(Keys.SUBSTITUTOR_NAME) final Function<String, String> stringSubstitutionStrategy) {
-        super(stringSubstitutionStrategy);
+    public PluginBuilderAttributeVisitor(
+            @Named(Keys.SUBSTITUTOR_NAME) final Function<String, String> stringSubstitutionStrategy,
+            final Injector injector) {
+        super(stringSubstitutionStrategy, injector);
     }
 
     @SuppressWarnings("deprecation")
diff --git a/log4j-couchdb/src/main/java/org/apache/logging/log4j/couchdb/CouchDbProvider.java b/log4j-couchdb/src/main/java/org/apache/logging/log4j/couchdb/CouchDbProvider.java
index 179096c..ad79830 100644
--- a/log4j-couchdb/src/main/java/org/apache/logging/log4j/couchdb/CouchDbProvider.java
+++ b/log4j-couchdb/src/main/java/org/apache/logging/log4j/couchdb/CouchDbProvider.java
@@ -16,14 +16,14 @@
  */
 package org.apache.logging.log4j.couchdb;
 
-import java.lang.reflect.Method;
-
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.appender.nosql.NoSqlProvider;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginAttribute;
 import org.apache.logging.log4j.plugins.PluginFactory;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
+import org.apache.logging.log4j.plugins.convert.TypeConverter;
+import org.apache.logging.log4j.plugins.di.Injector;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
 import org.apache.logging.log4j.plugins.validation.constraints.ValidHost;
 import org.apache.logging.log4j.plugins.validation.constraints.ValidPort;
 import org.apache.logging.log4j.status.StatusLogger;
@@ -32,6 +32,8 @@ import org.apache.logging.log4j.util.Strings;
 import org.lightcouch.CouchDbClient;
 import org.lightcouch.CouchDbProperties;
 
+import java.lang.reflect.Method;
+
 /**
  * The Apache CouchDB implementation of {@link NoSqlProvider}.
  */
@@ -89,7 +91,8 @@ public final class CouchDbProvider implements NoSqlProvider<CouchDbConnection> {
             @PluginAttribute final String username,
             @PluginAttribute(sensitive = true) final String password,
             @PluginAttribute final String factoryClassName,
-            @PluginAttribute final String factoryMethodName) {
+            @PluginAttribute final String factoryMethodName,
+            final Injector injector) {
         CouchDbClient client;
         String description;
         if (Strings.isNotEmpty(factoryClassName) && Strings.isNotEmpty(factoryMethodName)) {
@@ -139,7 +142,8 @@ public final class CouchDbProvider implements NoSqlProvider<CouchDbConnection> {
                 LOGGER.warn("No protocol specified, using default port [http].");
             }
 
-            final int portInt = TypeConverters.convert(port, int.class, protocol.equals("https") ? HTTPS : HTTP);
+            final TypeConverter<Integer> converter = TypeUtil.cast(injector.getTypeConverter(Integer.class));
+            final int portInt = converter.convert(port, protocol.equals("https") ? HTTPS : HTTP);
 
             if (Strings.isEmpty(username) || Strings.isEmpty(password)) {
                 LOGGER.error("You must provide a username and password for the CouchDB provider.");
diff --git a/log4j-jdbc/src/main/java/org/apache/logging/log4j/jdbc/appender/JdbcDatabaseManager.java b/log4j-jdbc/src/main/java/org/apache/logging/log4j/jdbc/appender/JdbcDatabaseManager.java
index 4e9239d..4477cf9 100644
--- a/log4j-jdbc/src/main/java/org/apache/logging/log4j/jdbc/appender/JdbcDatabaseManager.java
+++ b/log4j-jdbc/src/main/java/org/apache/logging/log4j/jdbc/appender/JdbcDatabaseManager.java
@@ -16,6 +16,24 @@
  */
 package org.apache.logging.log4j.jdbc.appender;
 
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.StringLayout;
+import org.apache.logging.log4j.core.appender.AppenderLoggingException;
+import org.apache.logging.log4j.core.appender.ManagerFactory;
+import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
+import org.apache.logging.log4j.core.appender.db.ColumnMapping;
+import org.apache.logging.log4j.core.appender.db.DbAppenderLoggingException;
+import org.apache.logging.log4j.core.util.Closer;
+import org.apache.logging.log4j.core.util.Log4jThread;
+import org.apache.logging.log4j.jdbc.convert.DateTypeConverter;
+import org.apache.logging.log4j.message.MapMessage;
+import org.apache.logging.log4j.spi.ThreadContextMap;
+import org.apache.logging.log4j.spi.ThreadContextStack;
+import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+import org.apache.logging.log4j.util.Strings;
+
 import java.io.Serializable;
 import java.io.StringReader;
 import java.sql.Clob;
@@ -38,25 +56,6 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.CountDownLatch;
 
-import org.apache.logging.log4j.core.Layout;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.StringLayout;
-import org.apache.logging.log4j.core.appender.AppenderLoggingException;
-import org.apache.logging.log4j.core.appender.ManagerFactory;
-import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
-import org.apache.logging.log4j.core.appender.db.ColumnMapping;
-import org.apache.logging.log4j.core.appender.db.DbAppenderLoggingException;
-import org.apache.logging.log4j.core.util.Closer;
-import org.apache.logging.log4j.core.util.Log4jThread;
-import org.apache.logging.log4j.jdbc.convert.DateTypeConverter;
-import org.apache.logging.log4j.message.MapMessage;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
-import org.apache.logging.log4j.spi.ThreadContextMap;
-import org.apache.logging.log4j.spi.ThreadContextStack;
-import org.apache.logging.log4j.util.IndexedReadOnlyStringMap;
-import org.apache.logging.log4j.util.ReadOnlyStringMap;
-import org.apache.logging.log4j.util.Strings;
-
 /**
  * An {@link AbstractDatabaseManager} implementation for relational databases accessed via JDBC.
  */
@@ -759,8 +758,7 @@ public final class JdbcDatabaseManager extends AbstractDatabaseManager {
                         } else if (NClob.class.isAssignableFrom(mapping.getType())) {
                             this.statement.setNClob(j++, new StringReader(layout.toSerializable(event)));
                         } else {
-                            final Object value = TypeConverters.convert(layout.toSerializable(event), mapping.getType(),
-                                    null);
+                            final Object value = mapping.getTypeConverter().convert(layout.toSerializable(event), null);
                             setStatementObject(j++, mapping.getNameKey(), value);
                         }
                     }
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryConverter.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryConverter.java
index 1de8039..546928f 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryConverter.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoryConverter.java
@@ -18,12 +18,11 @@ package org.apache.logging.log4j.layout.template.json.util;
 
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.convert.TypeConverter;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
 
 /**
  * The default string (i.e., recycler factory spec) to {@link RecyclerFactory} type converter.
  */
-@Plugin(name = "RecyclerFactoryConverter", category = TypeConverters.CATEGORY)
+@Plugin(name = "RecyclerFactoryConverter", category = TypeConverter.CATEGORY)
 public final class RecyclerFactoryConverter implements TypeConverter<RecyclerFactory> {
 
     @Override
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoriesTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoriesTest.java
index 23bfe05..1a9d235 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoriesTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactoriesTest.java
@@ -16,12 +16,13 @@
  */
 package org.apache.logging.log4j.layout.template.json.util;
 
-import org.apache.logging.log4j.plugins.convert.TypeConverter;
-import org.apache.logging.log4j.plugins.convert.TypeConverterRegistry;
+import org.apache.logging.log4j.core.test.appender.ListAppender;
 import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
 import org.apache.logging.log4j.core.test.junit.Named;
 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
-import org.apache.logging.log4j.core.test.appender.ListAppender;
+import org.apache.logging.log4j.plugins.convert.TypeConverter;
+import org.apache.logging.log4j.plugins.di.DI;
+import org.apache.logging.log4j.plugins.di.Injector;
 import org.assertj.core.api.Assertions;
 import org.jctools.queues.MpmcArrayQueue;
 import org.junit.jupiter.api.Test;
@@ -35,10 +36,10 @@ class RecyclerFactoriesTest {
     @Test
     void test_RecyclerFactoryConverter() throws Exception {
 
+        final Injector injector = DI.createInjector();
+        injector.init();
         // Check if the type converter is registered.
-        final TypeConverter<?> converter = TypeConverterRegistry
-                .getInstance()
-                .findCompatibleConverter(RecyclerFactory.class);
+        final TypeConverter<?> converter = injector.getTypeConverter(RecyclerFactory.class);
         Assertions.assertThat(converter).isNotNull();
 
         // Check dummy recycler factory.
diff --git a/log4j-mongodb3/src/main/java/org/apache/logging/log4j/mongodb3/MongoDb3Provider.java b/log4j-mongodb3/src/main/java/org/apache/logging/log4j/mongodb3/MongoDb3Provider.java
index 52e05b1..2a5f364 100644
--- a/log4j-mongodb3/src/main/java/org/apache/logging/log4j/mongodb3/MongoDb3Provider.java
+++ b/log4j-mongodb3/src/main/java/org/apache/logging/log4j/mongodb3/MongoDb3Provider.java
@@ -16,17 +16,23 @@
  */
 package org.apache.logging.log4j.mongodb3;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientOptions;
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
+import com.mongodb.WriteConcern;
+import com.mongodb.client.MongoDatabase;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.Core;
 import org.apache.logging.log4j.core.appender.nosql.NoSqlProvider;
 import org.apache.logging.log4j.core.filter.AbstractFilterable;
+import org.apache.logging.log4j.plugins.Inject;
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.PluginBuilderAttribute;
 import org.apache.logging.log4j.plugins.PluginFactory;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
+import org.apache.logging.log4j.plugins.convert.TypeConverter;
+import org.apache.logging.log4j.plugins.di.Injector;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
 import org.apache.logging.log4j.plugins.validation.constraints.Required;
 import org.apache.logging.log4j.plugins.validation.constraints.ValidHost;
 import org.apache.logging.log4j.plugins.validation.constraints.ValidPort;
@@ -36,12 +42,8 @@ import org.apache.logging.log4j.util.Strings;
 import org.bson.codecs.configuration.CodecRegistries;
 import org.bson.codecs.configuration.CodecRegistry;
 
-import com.mongodb.MongoClient;
-import com.mongodb.MongoClientOptions;
-import com.mongodb.MongoCredential;
-import com.mongodb.ServerAddress;
-import com.mongodb.WriteConcern;
-import com.mongodb.client.MongoDatabase;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 
 /**
  * The MongoDB implementation of {@link NoSqlProvider} using the MongoDB driver version 3 API.
@@ -125,6 +127,8 @@ public final class MongoDb3Provider implements NoSqlProvider<MongoDb3Connection>
         @PluginBuilderAttribute
         private String writeConcernConstantClassName;
 
+        private Injector injector;
+
         @SuppressWarnings("resource")
         @Override
         public MongoDb3Provider build() {
@@ -180,7 +184,8 @@ public final class MongoDb3Provider implements NoSqlProvider<MongoDb3Connection>
                     mongoCredential = MongoCredential.createCredential(userName, databaseName, password.toCharArray());
                 }
                 try {
-                    final int portInt = TypeConverters.convert(port, int.class, DEFAULT_PORT);
+                    final TypeConverter<Integer> converter = TypeUtil.cast(injector.getTypeConverter(Integer.class));
+                    final int portInt = converter.convert(port, DEFAULT_PORT);
                     description += ", server=" + server + ", port=" + portInt;
                     final WriteConcern writeConcern = toWriteConcern(writeConcernConstant, writeConcernConstantClassName);
                     // @formatter:off
@@ -286,6 +291,12 @@ public final class MongoDb3Provider implements NoSqlProvider<MongoDb3Connection>
             this.writeConcernConstantClassName = writeConcernConstantClassName;
             return asBuilder();
         }
+
+        @Inject
+        public B setInjector(final Injector injector) {
+            this.injector = injector;
+            return asBuilder();
+        }
     }
 
     private static final int DEFAULT_COLLECTION_SIZE = 536870912;
diff --git a/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugins/convert/TypeConverterRegistryTest.java b/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugins/convert/TypeConverterRegistryTest.java
index bf4303b..3b68ffa 100644
--- a/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugins/convert/TypeConverterRegistryTest.java
+++ b/log4j-plugins-test/src/test/java/org/apache/logging/log4j/plugins/convert/TypeConverterRegistryTest.java
@@ -18,6 +18,8 @@
 package org.apache.logging.log4j.plugins.convert;
 
 import org.apache.logging.log4j.plugins.Plugin;
+import org.apache.logging.log4j.plugins.di.DI;
+import org.apache.logging.log4j.plugins.di.Injector;
 import org.junit.jupiter.api.Test;
 
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -31,7 +33,7 @@ class TypeConverterRegistryTest {
 
     }
 
-    @Plugin(name = "CustomTestClass1Converter1", category = TypeConverters.CATEGORY)
+    @Plugin(name = "CustomTestClass1Converter1", category = TypeConverter.CATEGORY)
     public static final class CustomTestClass1Converter1
             implements TypeConverter<CustomTestClass1> {
 
@@ -43,7 +45,7 @@ class TypeConverterRegistryTest {
     }
 
     @SuppressWarnings("ComparableType")
-    @Plugin(name = "CustomTestClass1Converter2", category = TypeConverters.CATEGORY)
+    @Plugin(name = "CustomTestClass1Converter2", category = TypeConverter.CATEGORY)
     public static final class CustomTestClass1Converter2
             implements TypeConverter<CustomTestClass1>, Comparable<TypeConverter<?>> {
 
@@ -61,9 +63,9 @@ class TypeConverterRegistryTest {
 
     @Test
     public void testMultipleComparableConverters() {
-        final TypeConverter<?> converter = TypeConverterRegistry
-                .getInstance()
-                .findCompatibleConverter(CustomTestClass1.class);
+        final Injector injector = DI.createInjector();
+        injector.init();
+        final TypeConverter<?> converter = injector.getTypeConverter(CustomTestClass1.class);
         assertThat(converter, instanceOf(CustomTestClass1Converter2.class));
     }
 
@@ -73,7 +75,7 @@ class TypeConverterRegistryTest {
 
     }
 
-    @Plugin(name = "CustomTestClass2Converter1", category = TypeConverters.CATEGORY)
+    @Plugin(name = "CustomTestClass2Converter1", category = TypeConverter.CATEGORY)
     public static final class CustomTestClass2Converter1
             implements TypeConverter<CustomTestClass2> {
 
@@ -84,7 +86,7 @@ class TypeConverterRegistryTest {
 
     }
 
-    @Plugin(name = "CustomTestClass2Converter2", category = TypeConverters.CATEGORY)
+    @Plugin(name = "CustomTestClass2Converter2", category = TypeConverter.CATEGORY)
     public static final class CustomTestClass2Converter2
             implements TypeConverter<CustomTestClass2> {
 
@@ -97,9 +99,9 @@ class TypeConverterRegistryTest {
 
     @Test
     public void testMultipleIncomparableConverters() {
-        final TypeConverter<?> converter = TypeConverterRegistry
-                .getInstance()
-                .findCompatibleConverter(CustomTestClass2.class);
+        final Injector injector = DI.createInjector();
+        injector.init();
+        final TypeConverter<?> converter = injector.getTypeConverter(CustomTestClass2.class);
         assertThat(converter, instanceOf(CustomTestClass2Converter1.class));
     }
 
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverter.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverter.java
index 45e8a16..403ab57 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverter.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverter.java
@@ -17,16 +17,25 @@
 
 package org.apache.logging.log4j.plugins.convert;
 
+import org.apache.logging.log4j.plugins.Plugin;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
+import org.apache.logging.log4j.status.StatusLogger;
+
 /**
  * Interface for doing automatic String conversion to a specific type.
  *
  * @param <T> Converts Strings into the given type {@code T}.
- * @since 2.1 Moved to the {@code convert} package.
+ * @since 3.0.0 Moved to {@code log4j-plugins}.
  */
 @FunctionalInterface
 public interface TypeConverter<T> {
 
     /**
+     * The {@link Plugin#category() Plugin Category} to use for {@link TypeConverter} plugins.
+     */
+    String CATEGORY = "TypeConverter";
+
+    /**
      * Converts a String to a given type.
      *
      * @param s the String to convert. Cannot be {@code null}.
@@ -34,4 +43,31 @@ public interface TypeConverter<T> {
      * @throws Exception thrown when a conversion error occurs
      */
     T convert(String s) throws Exception;
+
+    default T convert(final String string, final Object defaultValue) {
+        return convert(string, defaultValue, false);
+    }
+
+    default T convert(final String string, final Object defaultValue, final boolean sensitive) {
+        if (string != null) {
+            try {
+                return convert(string);
+            } catch (final Exception e) {
+                StatusLogger.getLogger().warn("Unable to convert string [{}]. Using default value [{}].",
+                        sensitive ? "-redacted-" : string, defaultValue, e);
+            }
+        }
+        if (defaultValue == null) {
+            return null;
+        }
+        if (!(defaultValue instanceof String)) {
+            return TypeUtil.cast(defaultValue);
+        }
+        try {
+            return convert((String) defaultValue);
+        } catch (final Exception e) {
+            StatusLogger.getLogger().debug("Unable to parse default value [{}].", defaultValue, e);
+            return null;
+        }
+    }
 }
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverterRegistry.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverterRegistry.java
deleted file mode 100644
index 412265c..0000000
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverterRegistry.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * 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 org.apache.logging.log4j.plugins.convert;
-
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.plugins.util.PluginType;
-import org.apache.logging.log4j.plugins.util.PluginUtil;
-import org.apache.logging.log4j.plugins.util.TypeUtil;
-import org.apache.logging.log4j.status.StatusLogger;
-import org.apache.logging.log4j.util.LazyValue;
-import org.apache.logging.log4j.util.ReflectionUtil;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Objects;
-import java.util.UnknownFormatConversionException;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.function.Supplier;
-
-/**
- * Registry for {@link TypeConverter} plugins.
- *
- * @since 2.1
- */
-public class TypeConverterRegistry {
-
-    private static final Logger LOGGER = StatusLogger.getLogger();
-    private static final Supplier<TypeConverterRegistry> INSTANCE = new LazyValue<>(TypeConverterRegistry::new);
-
-    private final ConcurrentMap<Type, TypeConverter<?>> registry = new ConcurrentHashMap<>();
-
-    /**
-     * Gets the singleton instance of the TypeConverterRegistry.
-     *
-     * @return the singleton instance.
-     */
-    public static TypeConverterRegistry getInstance() {
-        return INSTANCE.get();
-    }
-
-    /**
-     * Finds a {@link TypeConverter} for the given {@link Type}, falling back to an assignment-compatible TypeConverter
-     * if none exist for the given type. That is, if the given Type does not have a TypeConverter, but another Type
-     * which can be assigned to the given Type <em>does</em> have a TypeConverter, then that TypeConverter will be
-     * used and registered.
-     *
-     * @param type the Type to find a TypeConverter for (must not be {@code null}).
-     * @return a TypeConverter for the given Type.
-     * @throws UnknownFormatConversionException if no TypeConverter can be found for the given type.
-     */
-    public TypeConverter<?> findCompatibleConverter(final Type type) {
-        Objects.requireNonNull(type, "No type was provided");
-        final TypeConverter<?> primary = registry.get(type);
-        // cached type converters
-        if (primary != null) {
-            return primary;
-        }
-        // dynamic enum support
-        if (type instanceof Class<?>) {
-            final Class<?> clazz = (Class<?>) type;
-            if (clazz.isEnum()) {
-                @SuppressWarnings({"unchecked","rawtypes"})
-                final EnumConverter<? extends Enum> converter = new EnumConverter(clazz.asSubclass(Enum.class));
-                synchronized (INSTANCE) {
-                    return registerConverter(type, converter);
-                }
-            }
-        }
-        // look for compatible converters
-        for (final Map.Entry<Type, TypeConverter<?>> entry : registry.entrySet()) {
-            final Type key = entry.getKey();
-            if (TypeUtil.isAssignable(type, key)) {
-                LOGGER.debug("Found compatible TypeConverter<{}> for type [{}].", key, type);
-                final TypeConverter<?> value = entry.getValue();
-                synchronized (INSTANCE) {
-                    return registerConverter(type, value);
-                }
-            }
-        }
-        throw new UnknownFormatConversionException(type.toString());
-    }
-
-    private TypeConverterRegistry() {
-        LOGGER.trace("TypeConverterRegistry initializing.");
-        loadKnownTypeConverters(PluginUtil.collectPluginsByCategory(TypeConverters.CATEGORY).values());
-        registerPrimitiveTypes();
-    }
-
-    private void loadKnownTypeConverters(final Collection<PluginType<?>> knownTypes) {
-        for (final PluginType<?> knownType : knownTypes) {
-            final Class<?> clazz = knownType.getPluginClass();
-            if (TypeConverter.class.isAssignableFrom(clazz)) {
-                @SuppressWarnings("rawtypes") final Class<? extends TypeConverter> pluginClass =
-                        clazz.asSubclass(TypeConverter.class);
-                final Type conversionType = getTypeConverterSupportedType(pluginClass);
-                final TypeConverter<?> converter = ReflectionUtil.instantiate(pluginClass);
-                registerConverter(conversionType, converter);
-            }
-        }
-    }
-
-    /**
-     * Attempts to register the given converter and returns the effective
-     * converter associated with the given type.
-     * <p>
-     * Registration will fail if there already exists a converter for the given
-     * type and neither the existing, nor the provided converter extends from {@link Comparable}.
-     */
-    private TypeConverter<?> registerConverter(
-            final Type conversionType,
-            final TypeConverter<?> converter) {
-        final TypeConverter<?> conflictingConverter = registry.get(conversionType);
-        if (conflictingConverter != null) {
-            final boolean overridable;
-            if (converter instanceof Comparable) {
-                @SuppressWarnings("unchecked")
-                final Comparable<TypeConverter<?>> comparableConverter =
-                        (Comparable<TypeConverter<?>>) converter;
-                overridable = comparableConverter.compareTo(conflictingConverter) < 0;
-            } else if (conflictingConverter instanceof Comparable) {
-                @SuppressWarnings("unchecked")
-                final Comparable<TypeConverter<?>> comparableConflictingConverter =
-                        (Comparable<TypeConverter<?>>) conflictingConverter;
-                overridable = comparableConflictingConverter.compareTo(converter) > 0;
-            } else {
-                overridable = false;
-            }
-            if (overridable) {
-                LOGGER.debug(
-                        "Replacing TypeConverter [{}] for type [{}] with [{}] after comparison.",
-                        conflictingConverter, conversionType, converter);
-                registry.put(conversionType, converter);
-                return converter;
-            } else {
-                LOGGER.warn(
-                        "Ignoring TypeConverter [{}] for type [{}] that conflicts with [{}], since they are not comparable.",
-                        converter, conversionType, conflictingConverter);
-                return conflictingConverter;
-            }
-        } else {
-            registry.put(conversionType, converter);
-            return converter;
-        }
-    }
-
-    private static Type getTypeConverterSupportedType(@SuppressWarnings("rawtypes") final Class<? extends TypeConverter> typeConverterClass) {
-        for (final Type type : typeConverterClass.getGenericInterfaces()) {
-            if (type instanceof ParameterizedType) {
-                final ParameterizedType pType = (ParameterizedType) type;
-                if (TypeConverter.class.equals(pType.getRawType())) {
-                    // TypeConverter<T> has only one type argument (T), so return that
-                    return pType.getActualTypeArguments()[0];
-                }
-            }
-        }
-        return Void.TYPE;
-    }
-
-    private void registerPrimitiveTypes() {
-        registerConverter(Boolean.class, Boolean::valueOf);
-        registerTypeAlias(Boolean.class, Boolean.TYPE);
-        registerConverter(Byte.class, Byte::valueOf);
-        registerTypeAlias(Byte.class, Byte.TYPE);
-        registerConverter(Character.class, s -> {
-            if (s.length() != 1) {
-                throw new IllegalArgumentException("Character string must be of length 1: " + s);
-            }
-            return s.toCharArray()[0];
-        });
-        registerTypeAlias(Character.class, Character.TYPE);
-        registerConverter(Double.class, Double::valueOf);
-        registerTypeAlias(Double.class, Double.TYPE);
-        registerConverter(Float.class, Float::valueOf);
-        registerTypeAlias(Float.class, Float.TYPE);
-        registerConverter(Integer.class, Integer::valueOf);
-        registerTypeAlias(Integer.class, Integer.TYPE);
-        registerConverter(Long.class, Long::valueOf);
-        registerTypeAlias(Long.class, Long.TYPE);
-        registerConverter(Short.class, Short::valueOf);
-        registerTypeAlias(Short.class, Short.TYPE);
-        registerConverter(String.class, s -> s);
-    }
-
-    private void registerTypeAlias(final Type knownType, final Type aliasType) {
-        TypeConverter<?> converter = registry.get(knownType);
-        if (converter != null) {
-            registry.putIfAbsent(aliasType, converter);
-        } else {
-            LOGGER.error("Cannot locate converter for {}", knownType);
-        }
-    }
-
-}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverters.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverters.java
deleted file mode 100644
index 0ce0717..0000000
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/convert/TypeConverters.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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 org.apache.logging.log4j.plugins.convert;
-
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.plugins.Plugin;
-import org.apache.logging.log4j.plugins.util.TypeUtil;
-import org.apache.logging.log4j.status.StatusLogger;
-
-import java.lang.reflect.Type;
-
-/**
- * Collection of basic TypeConverter implementations. May be used to register additional TypeConverters or find
- * registered TypeConverters.
- *
- * @since 2.1 Moved to the {@code convert} package.
- */
-public final class TypeConverters {
-
-    /**
-     * The {@link Plugin#category() Plugin Category} to use for {@link TypeConverter} plugins.
-     *
-     * @since 2.1
-     */
-    public static final String CATEGORY = "TypeConverter";
-
-    /**
-     * Converts a String to a given class if a TypeConverter is available for that class. Falls back to the provided
-     * default value if the conversion is unsuccessful. However, if the default value is <em>also</em> invalid, then
-     * {@code null} is returned (along with a nasty status log message).
-     *
-     * @param s
-     *        the string to convert
-     * @param clazz
-     *        the class to try to convert the string to
-     * @param defaultValue
-     *        the fallback object to use if the conversion is unsuccessful
-     * @param <T> The type of the clazz parameter.
-     * @return the converted object which may be {@code null} if the string is invalid for the given type
-     * @throws NullPointerException
-     *         if {@code clazz} is {@code null}
-     * @throws IllegalArgumentException
-     *         if no TypeConverter exists for the given class
-     */
-    public static <T> T convert(final String s, final Class<? extends T> clazz, final Object defaultValue) {
-        return convert(s, clazz, defaultValue, false);
-    }
-
-    public static <T> T convert(final String s, final Type targetType, final Object defaultValue, final boolean sensitive) {
-        final TypeConverter<T> converter =
-                TypeUtil.cast(TypeConverterRegistry.getInstance().findCompatibleConverter(targetType));
-        if (s == null) {
-            return parseDefaultValue(converter, defaultValue);
-        }
-        try {
-            return converter.convert(s);
-        } catch (final Exception e) {
-            LOGGER.warn("Error while converting string [{}] to type [{}]. Using default value [{}].",
-                    sensitive ? "-redacted-" : s, targetType, defaultValue, e);
-            return parseDefaultValue(converter, defaultValue);
-        }
-    }
-
-    private static <T> T parseDefaultValue(final TypeConverter<T> converter, final Object defaultValue) {
-        if (defaultValue == null) {
-            return null;
-        }
-        if (!(defaultValue instanceof String)) {
-            return TypeUtil.cast(defaultValue);
-        }
-        try {
-            return converter.convert((String) defaultValue);
-        } catch (final Exception e) {
-            LOGGER.debug("Can't parse default value [{}] for type [{}].", defaultValue, converter.getClass(), e);
-            return null;
-        }
-    }
-
-    private static final Logger LOGGER = StatusLogger.getLogger();
-
-}
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
index 1937234..6d62cce 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/DefaultInjector.java
@@ -25,6 +25,7 @@ import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.plugins.QualifierType;
 import org.apache.logging.log4j.plugins.ScopeType;
 import org.apache.logging.log4j.plugins.Singleton;
+import org.apache.logging.log4j.plugins.convert.TypeConverter;
 import org.apache.logging.log4j.plugins.name.AnnotatedElementAliasesProvider;
 import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
 import org.apache.logging.log4j.plugins.util.AnnotationUtil;
@@ -36,6 +37,7 @@ import org.apache.logging.log4j.plugins.validation.ConstraintValidationException
 import org.apache.logging.log4j.plugins.validation.ConstraintValidator;
 import org.apache.logging.log4j.plugins.visit.NodeVisitor;
 import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.util.EnglishEnums;
 import org.apache.logging.log4j.util.LazyValue;
 import org.apache.logging.log4j.util.ServiceRegistry;
 import org.apache.logging.log4j.util.StringBuilders;
@@ -63,6 +65,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.ServiceLoader;
 import java.util.Set;
+import java.util.UnknownFormatConversionException;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
@@ -73,6 +76,7 @@ class DefaultInjector implements Injector {
 
     private final BindingMap bindingMap;
     private final Map<Class<? extends Annotation>, Scope> scopes = new ConcurrentHashMap<>();
+    private final Map<Type, TypeConverter<?>> typeConverters = new ConcurrentHashMap<>();
     private ReflectionAccessor accessor = object -> object.setAccessible(true);
 
     DefaultInjector() {
@@ -84,6 +88,7 @@ class DefaultInjector implements Injector {
     DefaultInjector(final DefaultInjector original) {
         bindingMap = new BindingMap(original.bindingMap);
         scopes.putAll(original.scopes);
+        typeConverters.putAll(original.typeConverters);
         accessor = original.accessor;
     }
 
@@ -112,6 +117,40 @@ class DefaultInjector implements Injector {
     }
 
     @Override
+    public TypeConverter<?> getTypeConverter(final Type type) {
+        if (typeConverters.isEmpty()) {
+            synchronized (typeConverters) {
+                if (typeConverters.isEmpty()) {
+                    LOGGER.trace("Initializing type converters");
+                    initializeTypeConverters();
+                }
+            }
+        }
+        final TypeConverter<?> primary = typeConverters.get(type);
+        // cached type converters
+        if (primary != null) {
+            return primary;
+        }
+        // dynamic enum support
+        if (type instanceof Class<?>) {
+            final Class<?> clazz = (Class<?>) type;
+            if (clazz.isEnum()) {
+                return registerTypeConverter(type, s -> EnglishEnums.valueOf(clazz.asSubclass(Enum.class), s));
+            }
+        }
+        // look for compatible converters
+        for (final Map.Entry<Type, TypeConverter<?>> entry : typeConverters.entrySet()) {
+            final Type key = entry.getKey();
+            if (TypeUtil.isAssignable(type, key)) {
+                LOGGER.debug("Found compatible TypeConverter<{}> for type [{}].", key, type);
+                final TypeConverter<?> value = entry.getValue();
+                return registerTypeConverter(type, value);
+            }
+        }
+        throw new UnknownFormatConversionException(type.toString());
+    }
+
+    @Override
     public void injectMembers(final Object instance) {
         injectMembers(Key.forClass(instance.getClass()), null, instance, Set.of(), null);
     }
@@ -253,6 +292,83 @@ class DefaultInjector implements Injector {
         }
     }
 
+    private void initializeTypeConverters() {
+        final PluginManager manager = getInstance(new @Named(TypeConverter.CATEGORY) Key<>() {});
+        manager.collectPlugins();
+        for (final PluginType<?> knownType : manager.getPlugins().values()) {
+            final Class<?> pluginClass = knownType.getPluginClass();
+            final Type type = getTypeConverterSupportedType(pluginClass);
+            final TypeConverter<?> converter = getInstance(pluginClass.asSubclass(TypeConverter.class));
+            registerTypeConverter(type, converter);
+        }
+        registerTypeConverter(Boolean.class, Boolean::valueOf);
+        registerTypeAlias(Boolean.class, Boolean.TYPE);
+        registerTypeConverter(Byte.class, Byte::valueOf);
+        registerTypeAlias(Byte.class, Byte.TYPE);
+        registerTypeConverter(Character.class, s -> {
+            if (s.length() != 1) {
+                throw new IllegalArgumentException("Character string must be of length 1: " + s);
+            }
+            return s.toCharArray()[0];
+        });
+        registerTypeAlias(Character.class, Character.TYPE);
+        registerTypeConverter(Double.class, Double::valueOf);
+        registerTypeAlias(Double.class, Double.TYPE);
+        registerTypeConverter(Float.class, Float::valueOf);
+        registerTypeAlias(Float.class, Float.TYPE);
+        registerTypeConverter(Integer.class, Integer::valueOf);
+        registerTypeAlias(Integer.class, Integer.TYPE);
+        registerTypeConverter(Long.class, Long::valueOf);
+        registerTypeAlias(Long.class, Long.TYPE);
+        registerTypeConverter(Short.class, Short::valueOf);
+        registerTypeAlias(Short.class, Short.TYPE);
+        registerTypeConverter(String.class, s -> s);
+    }
+
+    private TypeConverter<?> registerTypeConverter(final Type type, final TypeConverter<?> converter) {
+        final TypeConverter<?> conflictingConverter = typeConverters.get(type);
+        if (conflictingConverter != null) {
+            final boolean overridable;
+            if (converter instanceof Comparable) {
+                @SuppressWarnings("unchecked")
+                final Comparable<TypeConverter<?>> comparableConverter =
+                        (Comparable<TypeConverter<?>>) converter;
+                overridable = comparableConverter.compareTo(conflictingConverter) < 0;
+            } else if (conflictingConverter instanceof Comparable) {
+                @SuppressWarnings("unchecked")
+                final Comparable<TypeConverter<?>> comparableConflictingConverter =
+                        (Comparable<TypeConverter<?>>) conflictingConverter;
+                overridable = comparableConflictingConverter.compareTo(converter) > 0;
+            } else {
+                overridable = false;
+            }
+            if (overridable) {
+                LOGGER.debug(
+                        "Replacing TypeConverter [{}] for type [{}] with [{}] after comparison.",
+                        conflictingConverter, type, converter);
+                typeConverters.put(type, converter);
+                return converter;
+            } else {
+                LOGGER.warn(
+                        "Ignoring TypeConverter [{}] for type [{}] that conflicts with [{}], since they are not comparable.",
+                        converter, type, conflictingConverter);
+                return conflictingConverter;
+            }
+        } else {
+            typeConverters.put(type, converter);
+            return converter;
+        }
+    }
+
+    private void registerTypeAlias(final Type knownType, final Type aliasType) {
+        final TypeConverter<?> converter = typeConverters.get(knownType);
+        if (converter != null) {
+            typeConverters.put(aliasType, converter);
+        } else {
+            LOGGER.error("Cannot locate type converter for {}", knownType);
+        }
+    }
+
     private void injectMembers(
             final Key<?> key, final Node node, final Object instance, final Set<Key<?>> chain, final StringBuilder debugLog) {
         injectFields(key.getRawType(), node, instance, debugLog);
@@ -495,6 +611,18 @@ class DefaultInjector implements Injector {
         ((ConstraintValidator) validator).initialize(annotation);
     }
 
+    private static Type getTypeConverterSupportedType(final Class<?> clazz) {
+        for (final Type type : clazz.getGenericInterfaces()) {
+            if (type instanceof ParameterizedType) {
+                final ParameterizedType parameterizedType = (ParameterizedType) type;
+                if (parameterizedType.getRawType() == TypeConverter.class) {
+                    return parameterizedType.getActualTypeArguments()[0];
+                }
+            }
+        }
+        return Void.TYPE;
+    }
+
     private static void verifyAttributesConsumed(final Node node) {
         final Map<String, String> attrs = node.getAttributes();
         if (!attrs.isEmpty()) {
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
index b51d845..24a0ee9 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/di/Injector.java
@@ -19,8 +19,10 @@ package org.apache.logging.log4j.plugins.di;
 
 import org.apache.logging.log4j.plugins.FactoryType;
 import org.apache.logging.log4j.plugins.Node;
+import org.apache.logging.log4j.plugins.convert.TypeConverter;
 
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
 import java.util.function.Supplier;
 
 /**
@@ -87,6 +89,15 @@ public interface Injector {
     }
 
     /**
+     * Gets a TypeConverter for the provided type.
+     *
+     * @param type type to get a converter for
+     * @return a TypeConverter for the provided type
+     * @throws java.util.UnknownFormatConversionException if no converter can be found for the provided type
+     */
+    TypeConverter<?> getTypeConverter(final Type type);
+
+    /**
      * Injects dependencies into the members of the provided instance. Injectable fields are set, then injectable methods are
      * invoked (first those with parameters, then those without parameters).
      *
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/validators/ValidPortValidator.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/validators/ValidPortValidator.java
index 27e97f0..a65fecc 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/validators/ValidPortValidator.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/validation/validators/ValidPortValidator.java
@@ -17,9 +17,12 @@
 package org.apache.logging.log4j.plugins.validation.validators;
 
 import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.plugins.Inject;
+import org.apache.logging.log4j.plugins.convert.TypeConverter;
+import org.apache.logging.log4j.plugins.di.Injector;
+import org.apache.logging.log4j.plugins.util.TypeUtil;
 import org.apache.logging.log4j.plugins.validation.ConstraintValidator;
 import org.apache.logging.log4j.plugins.validation.constraints.ValidPort;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
 import org.apache.logging.log4j.status.StatusLogger;
 
 /**
@@ -31,8 +34,14 @@ public class ValidPortValidator implements ConstraintValidator<ValidPort> {
 
     private static final Logger LOGGER = StatusLogger.getLogger();
 
+    private final TypeConverter<Integer> converter;
     private ValidPort annotation;
 
+    @Inject
+    public ValidPortValidator(final Injector injector) {
+        converter = TypeUtil.cast(injector.getTypeConverter(Integer.class));
+    }
+
     @Override
     public void initialize(final ValidPort annotation) {
         this.annotation = annotation;
@@ -41,9 +50,9 @@ public class ValidPortValidator implements ConstraintValidator<ValidPort> {
     @Override
     public boolean isValid(final String name, final Object value) {
         if (value instanceof CharSequence) {
-            return isValid(name, TypeConverters.convert(value.toString(), Integer.class, -1));
+            return isValid(name, converter.convert(value.toString(), -1));
         }
-        if (!Integer.class.isInstance(value)) {
+        if (!(value instanceof Integer)) {
             LOGGER.error(annotation.message());
             return false;
         }
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/visit/PluginAttributeVisitor.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/visit/PluginAttributeVisitor.java
index 58cae4f..600f684 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/visit/PluginAttributeVisitor.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/visit/PluginAttributeVisitor.java
@@ -21,7 +21,8 @@ import org.apache.logging.log4j.plugins.Inject;
 import org.apache.logging.log4j.plugins.Named;
 import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.plugins.PluginAttribute;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
+import org.apache.logging.log4j.plugins.convert.TypeConverter;
+import org.apache.logging.log4j.plugins.di.Injector;
 import org.apache.logging.log4j.plugins.di.Keys;
 import org.apache.logging.log4j.plugins.name.AnnotatedElementAliasesProvider;
 import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
@@ -59,10 +60,14 @@ public class PluginAttributeVisitor implements NodeVisitor {
     );
 
     private final Function<String, String> stringSubstitutionStrategy;
+    private final Injector injector;
 
     @Inject
-    public PluginAttributeVisitor(@Named(Keys.SUBSTITUTOR_NAME) final Function<String, String> stringSubstitutionStrategy) {
+    public PluginAttributeVisitor(
+            @Named(Keys.SUBSTITUTOR_NAME) final Function<String, String> stringSubstitutionStrategy,
+            final Injector injector) {
         this.stringSubstitutionStrategy = stringSubstitutionStrategy;
+        this.injector = injector;
     }
 
     @Override
@@ -72,8 +77,9 @@ public class PluginAttributeVisitor implements NodeVisitor {
         final PluginAttribute annotation = field.getAnnotation(PluginAttribute.class);
         final boolean sensitive = annotation.sensitive();
         final Type targetType = field.getGenericType();
+        final TypeConverter<?> converter = injector.getTypeConverter(targetType);
         final Object value = node.removeMatchingAttribute(name, aliases)
-                .map(stringSubstitutionStrategy.andThen(s -> TypeConverters.convert(s, targetType, null, sensitive)))
+                .map(stringSubstitutionStrategy.andThen(s -> (Object) converter.convert(s, null, sensitive)))
                 .orElseGet(() -> getDefaultValue(targetType, annotation));
         StringBuilders.appendKeyDqValueWithJoiner(debugLog, name, sensitive ? "(***)" : value, ", ");
         return value;
@@ -84,10 +90,11 @@ public class PluginAttributeVisitor implements NodeVisitor {
         final String name = AnnotatedElementNameProvider.getName(parameter);
         final Collection<String> aliases = AnnotatedElementAliasesProvider.getAliases(parameter);
         final Type targetType = parameter.getParameterizedType();
+        final TypeConverter<?> converter = injector.getTypeConverter(targetType);
         final PluginAttribute annotation = parameter.getAnnotation(PluginAttribute.class);
         final boolean sensitive = annotation.sensitive();
         final Object value = node.removeMatchingAttribute(name, aliases)
-                .map(stringSubstitutionStrategy.andThen(s -> TypeConverters.convert(s, targetType, null, sensitive)))
+                .map(stringSubstitutionStrategy.andThen(s -> (Object) converter.convert(s, null, sensitive)))
                 .orElseGet(() -> getDefaultValue(targetType, annotation));
         StringBuilders.appendKeyDqValueWithJoiner(debugLog, name, sensitive ? "(***)" : value, ", ");
         return value;
@@ -98,7 +105,8 @@ public class PluginAttributeVisitor implements NodeVisitor {
         if (extractor != null) {
             return extractor.apply(annotation);
         }
+        final TypeConverter<?> converter = injector.getTypeConverter(targetType);
         final var value = stringSubstitutionStrategy.apply(annotation.defaultString());
-        return Strings.isEmpty(value) ? null : TypeConverters.convert(value, targetType, null, false);
+        return Strings.isEmpty(value) ? null : converter.convert(value, null);
     }
 }
diff --git a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/visit/PluginBuilderAttributeVisitor.java b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/visit/PluginBuilderAttributeVisitor.java
index 9a381f2..19f0c3e 100644
--- a/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/visit/PluginBuilderAttributeVisitor.java
+++ b/log4j-plugins/src/main/java/org/apache/logging/log4j/plugins/visit/PluginBuilderAttributeVisitor.java
@@ -21,7 +21,8 @@ import org.apache.logging.log4j.plugins.Inject;
 import org.apache.logging.log4j.plugins.Named;
 import org.apache.logging.log4j.plugins.Node;
 import org.apache.logging.log4j.plugins.PluginBuilderAttribute;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
+import org.apache.logging.log4j.plugins.convert.TypeConverter;
+import org.apache.logging.log4j.plugins.di.Injector;
 import org.apache.logging.log4j.plugins.di.Keys;
 import org.apache.logging.log4j.plugins.name.AnnotatedElementAliasesProvider;
 import org.apache.logging.log4j.plugins.name.AnnotatedElementNameProvider;
@@ -36,10 +37,14 @@ import java.util.function.Function;
 
 public class PluginBuilderAttributeVisitor implements NodeVisitor {
     private final Function<String, String> stringSubstitutionStrategy;
+    private final Injector injector;
 
     @Inject
-    public PluginBuilderAttributeVisitor(@Named(Keys.SUBSTITUTOR_NAME) final Function<String, String> stringSubstitutionStrategy) {
+    public PluginBuilderAttributeVisitor(
+            @Named(Keys.SUBSTITUTOR_NAME) final Function<String, String> stringSubstitutionStrategy,
+            final Injector injector) {
         this.stringSubstitutionStrategy = stringSubstitutionStrategy;
+        this.injector = injector;
     }
 
     protected boolean isSensitive(final AnnotatedElement element) {
@@ -51,9 +56,10 @@ public class PluginBuilderAttributeVisitor implements NodeVisitor {
         final String name = AnnotatedElementNameProvider.getName(field);
         final Collection<String> aliases = AnnotatedElementAliasesProvider.getAliases(field);
         final Type targetType = field.getGenericType();
+        final TypeConverter<?> converter = injector.getTypeConverter(targetType);
         final boolean sensitive = isSensitive(field);
         final Object value = node.removeMatchingAttribute(name, aliases)
-                .map(stringSubstitutionStrategy.andThen(s -> TypeConverters.convert(s, targetType, null, sensitive)))
+                .map(stringSubstitutionStrategy.andThen(s -> converter.convert(s, null, sensitive)))
                 .orElse(null);
         StringBuilders.appendKeyDqValueWithJoiner(debugLog, name, sensitive ? "(***)" : value, ", ");
         return value;
@@ -64,9 +70,10 @@ public class PluginBuilderAttributeVisitor implements NodeVisitor {
         final String name = AnnotatedElementNameProvider.getName(parameter);
         final Collection<String> aliases = AnnotatedElementAliasesProvider.getAliases(parameter);
         final Type targetType = parameter.getParameterizedType();
+        final TypeConverter<?> converter = injector.getTypeConverter(targetType);
         final boolean sensitive = isSensitive(parameter);
         final Object value = node.removeMatchingAttribute(name, aliases)
-                .map(stringSubstitutionStrategy.andThen(s -> TypeConverters.convert(s, targetType, null, sensitive)))
+                .map(stringSubstitutionStrategy.andThen(s -> converter.convert(s, null, sensitive)))
                 .orElse(null);
         StringBuilders.appendKeyDqValueWithJoiner(debugLog, name, sensitive ? "(***)" : value, ", ");
         return value;
diff --git a/src/site/asciidoc/manual/json-template-layout.adoc.vm b/src/site/asciidoc/manual/json-template-layout.adoc.vm
index 8e86a8c..9e1b10e 100644
--- a/src/site/asciidoc/manual/json-template-layout.adoc.vm
+++ b/src/site/asciidoc/manual/json-template-layout.adoc.vm
@@ -1788,9 +1788,8 @@ package com.acme.logging.log4j.layout.template.json;
 
 import org.apache.logging.log4j.plugins.Plugin;
 import org.apache.logging.log4j.plugins.convert.TypeConverter;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
 
-@Plugin(name = "AcmeRecyclerFactoryConverter", category = TypeConverters.CATEGORY)
+@Plugin(name = "AcmeRecyclerFactoryConverter", category = TypeConverter.CATEGORY)
 public final class AcmeRecyclerFactoryConverter
         implements TypeConverter<RecyclerFactory>, Comparable<TypeConverter<?>> {
 

[logging-log4j2] 01/03: Disable compiler forking

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 455457f9841090ec824987360f37d8fa77a46035
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sat Mar 26 21:47:48 2022 -0500

    Disable compiler forking
    
    This option seems to be a relic from when multiple compilers were needed to build the project. By not forking, not only does this decrease the build time, it also improves the error messages and logging from annotation processors.
    
    Signed-off-by: Matt Sicker <ma...@apache.org>
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index c32d174..98daee4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1136,7 +1136,7 @@
             <showWarnings>true</showWarnings>
             <verbose>false</verbose>
             <encoding>UTF-8</encoding>
-            <fork>true</fork>
+            <fork>false</fork>
             <meminitial>256</meminitial>
             <maxmem>1024</maxmem>
             <compilerArgs>

[logging-log4j2] 02/03: Remove unused imports

Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 088f15fc248a0c164e6a62d8680bd4352fcd7f24
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sat Mar 26 21:48:26 2022 -0500

    Remove unused imports
    
    Signed-off-by: Matt Sicker <ma...@apache.org>
---
 .../logging/log4j/layout/template/json/util/RecyclerFactories.java     | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactories.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactories.java
index bbd724e..08afbe3 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactories.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/util/RecyclerFactories.java
@@ -17,9 +17,6 @@
 package org.apache.logging.log4j.layout.template.json.util;
 
 import org.apache.logging.log4j.core.util.Constants;
-import org.apache.logging.log4j.plugins.Plugin;
-import org.apache.logging.log4j.plugins.convert.TypeConverter;
-import org.apache.logging.log4j.plugins.convert.TypeConverters;
 import org.apache.logging.log4j.util.LoaderUtil;
 import org.jctools.queues.MpmcArrayQueue;