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

tallison pushed a commit to branch TIKA-4613
in repository https://gitbox.apache.org/repos/asf/tika.git

commit 54283f483e04c8dd2f09a1b77dfe17f3ea0d492e
Author: tallison <[email protected]>
AuthorDate: Tue Jan 6 15:41:44 2026 -0500

    TIKA-4613 -- look for jsonconfig constructor, fall back to no-arg
---
 .../org/apache/tika/serialization/TikaModule.java     | 13 ++++---------
 .../tika/metadata/filter/TestMetadataFilter.java      | 19 +++++++++++++++++++
 2 files changed, 23 insertions(+), 9 deletions(-)

diff --git 
a/tika-serialization/src/main/java/org/apache/tika/serialization/TikaModule.java
 
b/tika-serialization/src/main/java/org/apache/tika/serialization/TikaModule.java
index 249f7f71cf..181e6b90e1 100644
--- 
a/tika-serialization/src/main/java/org/apache/tika/serialization/TikaModule.java
+++ 
b/tika-serialization/src/main/java/org/apache/tika/serialization/TikaModule.java
@@ -227,12 +227,9 @@ public class TikaModule extends SimpleModule {
      */
     private static class TikaComponentDeserializer extends 
JsonDeserializer<Object> {
         private final Class<?> expectedType;
-        // Plain mapper for property updates (avoids infinite recursion with 
registered types)
-        private final ObjectMapper plainMapper;
 
         TikaComponentDeserializer(Class<?> expectedType) {
             this.expectedType = expectedType;
-            this.plainMapper = new ObjectMapper();
         }
 
         @Override
@@ -307,19 +304,17 @@ public class TikaModule extends SimpleModule {
                 } else if (cleanedConfig == null || cleanedConfig.isEmpty()) {
                     // If no config, use default constructor
                     instance = clazz.getDeclaredConstructor().newInstance();
-                } else if (SelfConfiguring.class.isAssignableFrom(clazz)) {
-                    // SelfConfiguring components: prefer JsonConfig 
constructor if available
+                } else {
+                    // Try JsonConfig constructor first (works for any 
component)
                     Constructor<?> jsonConfigCtor = 
findJsonConfigConstructor(clazz);
                     if (jsonConfigCtor != null) {
                         String json = mapper.writeValueAsString(cleanedConfig);
                         instance = jsonConfigCtor.newInstance((JsonConfig) () 
-> json);
                     } else {
+                        // Fall back to no-arg constructor + Jackson bean 
deserialization
                         instance = 
clazz.getDeclaredConstructor().newInstance();
+                        
mapper.readerForUpdating(instance).readValue(cleanedConfig);
                     }
-                } else {
-                    // Non-SelfConfiguring: use Jackson bean deserialization
-                    instance = clazz.getDeclaredConstructor().newInstance();
-                    
plainMapper.readerForUpdating(instance).readValue(cleanedConfig);
                 }
 
                 // Call initialize() on Initializable components
diff --git 
a/tika-serialization/src/test/java/org/apache/tika/metadata/filter/TestMetadataFilter.java
 
b/tika-serialization/src/test/java/org/apache/tika/metadata/filter/TestMetadataFilter.java
index 197a116702..04363eeec3 100644
--- 
a/tika-serialization/src/test/java/org/apache/tika/metadata/filter/TestMetadataFilter.java
+++ 
b/tika-serialization/src/test/java/org/apache/tika/metadata/filter/TestMetadataFilter.java
@@ -283,6 +283,25 @@ public class TestMetadataFilter extends TikaTest {
         assertEquals(2, metadata.names().length);
     }
 
+    /**
+     * Test that TikaModule correctly instantiates components that only have a 
JsonConfig
+     * constructor (no no-arg constructor). This verifies the fix for 
TIKA-4582.
+     */
+    @Test
+    public void testJsonConfigOnlyFilter() throws Exception {
+        TikaLoader loader = TikaLoader.load(getConfigPath(getClass(), 
"TIKA-4582-json-config-only.json"));
+        Metadata metadata = new Metadata();
+        metadata.set("title", "my title");
+        metadata.set("author", "my author");
+
+        MetadataFilter filter = loader.get(MetadataFilter.class);
+        metadata = filterOne(filter, metadata);
+
+        assertEquals(2, metadata.size());
+        assertEquals("TEST_my title", metadata.get("title"));
+        assertEquals("TEST_my author", metadata.get("author"));
+    }
+
     private static Metadata filterOne(MetadataFilter filter, Metadata 
singleMetadata) throws TikaException {
         List<Metadata> list = new ArrayList<>();
         list.add(singleMetadata);

Reply via email to