CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-dropwizard--dropwizard-jackson

Provides comprehensive Jackson JSON processing support for Dropwizard applications with pre-configured ObjectMapper instances and essential modules.

Pending
Overview
Eval results
Files

subtype-discovery.mddocs/

Subtype Discovery

Dropwizard Jackson provides a service-based discovery mechanism for polymorphic configurations, allowing runtime loading of Jackson subtypes through META-INF/services files.

DiscoverableSubtypeResolver

A Jackson subtype resolver that discovers subtypes via META-INF/services configuration files.

public class DiscoverableSubtypeResolver extends StdSubtypeResolver {
    public DiscoverableSubtypeResolver()
    public DiscoverableSubtypeResolver(Class<?> rootKlass)
    public List<Class<?>> getDiscoveredSubtypes()
    protected ClassLoader getClassLoader()
    protected List<Class<?>> discoverServices(Class<?> klass)
}

Constructors

Default Constructor:

public DiscoverableSubtypeResolver()

Constructs a resolver that scans for subtypes of the Discoverable interface.

Custom Root Class Constructor:

public DiscoverableSubtypeResolver(Class<?> rootKlass)

Constructs a resolver that scans for subtypes of the provided root class.

Parameters:

  • rootKlass (Class<?>): The class to use for selecting the correct META-INF/services file

Instance Methods

getDiscoveredSubtypes():

public List<Class<?>> getDiscoveredSubtypes()

Returns the list of subtypes discovered from META-INF configuration files.

Returns: List<Class<?>> of discovered subtype classes

getClassLoader():

protected ClassLoader getClassLoader()

Returns the ClassLoader from the current class for resource loading.

Returns: Current ClassLoader instance

discoverServices():

protected List<Class<?>> discoverServices(Class<?> klass)

Discovers services in META-INF/services folder for the provided class.

Parameters:

  • klass (Class<?>): The class to lookup services for

Returns: List<Class<?>> of discovered service classes

Discoverable Interface

A tag interface that allows Dropwizard to load Jackson subtypes at runtime for polymorphic configurations.

public interface Discoverable {
}

Purpose: Marker interface for classes that should be automatically discovered as Jackson subtypes.

Usage Examples

Basic Polymorphic Configuration

// Base configuration class
public abstract class DatabaseConfig implements Discoverable {
    public abstract String getType();
}

// PostgreSQL implementation
public class PostgreSQLConfig extends DatabaseConfig {
    private String host;
    private int port;
    private String database;
    
    @Override
    public String getType() {
        return "postgresql";
    }
    
    // constructors, getters, setters...
}

// MySQL implementation  
public class MySQLConfig extends DatabaseConfig {
    private String connectionUrl;
    private String driver;
    
    @Override
    public String getType() {
        return "mysql";
    }
    
    // constructors, getters, setters...
}

META-INF/services Configuration

Create a file at META-INF/services/io.dropwizard.jackson.Discoverable:

com.example.config.PostgreSQLConfig
com.example.config.MySQLConfig

JSON Deserialization

ObjectMapper mapper = Jackson.newObjectMapper();
// DiscoverableSubtypeResolver is automatically configured

// JSON with type information
String json = """
{
    "type": "postgresql",
    "host": "localhost",
    "port": 5432,
    "database": "myapp"
}
""";

DatabaseConfig config = mapper.readValue(json, DatabaseConfig.class);
// Automatically deserializes to PostgreSQLConfig instance

Custom Root Class Discovery

// Custom base class for plugin discovery
public abstract class Plugin {
    public abstract String getName();
}

// Plugin implementation
public class LoggingPlugin extends Plugin {
    private String logLevel;
    
    @Override
    public String getName() {
        return "logging";
    }
    
    // implementation...
}

// Custom resolver for Plugin subtypes
DiscoverableSubtypeResolver pluginResolver = new DiscoverableSubtypeResolver(Plugin.class);
List<Class<?>> pluginTypes = pluginResolver.getDiscoveredSubtypes();

// Register with ObjectMapper
ObjectMapper mapper = new ObjectMapper();
mapper.setSubtypeResolver(pluginResolver);

Service File for Custom Root Class

Create META-INF/services/com.example.Plugin:

com.example.plugins.LoggingPlugin
com.example.plugins.SecurityPlugin
com.example.plugins.CachePlugin

Error Handling

The resolver handles common issues gracefully:

  • Missing Service Files: Logs warnings but continues processing
  • Class Not Found: Logs info messages for unavailable implementations
  • IO Errors: Logs warnings when service files cannot be read
  • Invalid Class Files: Skips classes that cannot be loaded

Integration with ObjectMapper

The resolver is automatically configured with Jackson factory methods:

ObjectMapper mapper = Jackson.newObjectMapper();
// DiscoverableSubtypeResolver is automatically set

ObjectMapper minimal = Jackson.newMinimalObjectMapper();
// Also includes DiscoverableSubtypeResolver for polymorphic support

Advanced Usage

Conditional Discovery

// Discover subtypes at runtime
DiscoverableSubtypeResolver resolver = new DiscoverableSubtypeResolver();
List<Class<?>> subtypes = resolver.getDiscoveredSubtypes();

// Filter subtypes based on runtime conditions
List<Class<?>> enabledSubtypes = subtypes.stream()
    .filter(clazz -> isFeatureEnabled(clazz))
    .collect(Collectors.toList());

// Create custom resolver with filtered types
ObjectMapper mapper = new ObjectMapper();
mapper.setSubtypeResolver(resolver);

Note: The discovery process occurs during resolver construction and scans the entire classpath for applicable service files.

Install with Tessl CLI

npx tessl i tessl/maven-io-dropwizard--dropwizard-jackson

docs

index.md

jackson-modules.md

object-mapper-factory.md

property-naming.md

subtype-discovery.md

tile.json