Dropwizard utility classes for data sizes, durations, enums, generics, resources, exceptions, JAR locations, and direct execution services.
—
Utilities for resource loading with context class loader fallback and exception chain analysis tools.
The Resources utility class provides helper methods to work with resources using appropriate class loaders.
public static URL getResource(String resourceName);Returns a URL pointing to the specified resource using intelligent class loader selection.
Parameters:
resourceName - The name of the resource to locateReturns: The URL of the resource
Throws:
IllegalArgumentException - If the resource is not foundClass Loader Selection:
Thread.currentThread().getContextClassLoader() when availableResources.class.getClassLoader() if context class loader is nullThis approach works correctly in various environments including app servers where different threads may have different class loaders.
import io.dropwizard.util.Resources;
import java.net.URL;
import java.io.InputStream;
// Load a resource from the classpath
URL configUrl = Resources.getResource("config/application.yml");
URL templateUrl = Resources.getResource("templates/email-template.html");
URL imageUrl = Resources.getResource("static/images/logo.png");
// Convert to InputStream for reading
try (InputStream configStream = configUrl.openStream()) {
// Read configuration file
byte[] configBytes = configStream.readAllBytes();
String configContent = new String(configBytes);
}public class ConfigurationLoader {
public Properties loadProperties(String resourceName) {
try {
URL resourceUrl = Resources.getResource(resourceName);
Properties props = new Properties();
try (InputStream input = resourceUrl.openStream()) {
props.load(input);
}
return props;
} catch (IllegalArgumentException e) {
throw new RuntimeException("Configuration file not found: " + resourceName, e);
} catch (IOException e) {
throw new RuntimeException("Failed to load configuration: " + resourceName, e);
}
}
}
// Usage
ConfigurationLoader loader = new ConfigurationLoader();
Properties appProps = loader.loadProperties("application.properties");
Properties dbProps = loader.loadProperties("database.properties");public class TemplateService {
public String loadTemplate(String templateName) {
try {
URL templateUrl = Resources.getResource("templates/" + templateName);
try (InputStream input = templateUrl.openStream()) {
return new String(input.readAllBytes(), StandardCharsets.UTF_8);
}
} catch (IllegalArgumentException e) {
throw new RuntimeException("Template not found: " + templateName, e);
} catch (IOException e) {
throw new RuntimeException("Failed to read template: " + templateName, e);
}
}
}
// Usage
TemplateService templateService = new TemplateService();
String emailTemplate = templateService.loadTemplate("email-notification.html");
String reportTemplate = templateService.loadTemplate("monthly-report.html");// In servlet or web application contexts where context class loader
// is set appropriately for resource discovery
public class WebResourceLoader {
public byte[] loadWebAsset(String assetPath) {
try {
// Resources.getResource will use the context class loader
// which is typically set correctly in web applications
URL assetUrl = Resources.getResource("static/" + assetPath);
try (InputStream input = assetUrl.openStream()) {
return input.readAllBytes();
}
} catch (IllegalArgumentException e) {
throw new RuntimeException("Web asset not found: " + assetPath, e);
} catch (IOException e) {
throw new RuntimeException("Failed to load web asset: " + assetPath, e);
}
}
}The Throwables utility class provides helper methods to work with exception objects and exception chains.
public static Optional<Throwable> findThrowableInChain(
Predicate<Throwable> condition,
Throwable t
);Search an exception chain for an exception matching a given condition.
Parameters:
condition - The condition predicate to match against each exception in the chaint - The head of the exception chain (can be null)Returns: An Optional containing the first matching exception in the chain, or empty if no match found
Search Behavior:
getCause()Optional if no match is found or if the input throwable is nullimport io.dropwizard.util.Throwables;
import java.util.Optional;
// Example exception chain
Exception rootCause = new SQLException("Connection failed");
Exception cause = new RuntimeException("Database error", rootCause);
Exception topLevel = new ServiceException("Service unavailable", cause);
// Find SQLException in the chain
Optional<Throwable> sqlEx = Throwables.findThrowableInChain(
ex -> ex instanceof SQLException,
topLevel
);
if (sqlEx.isPresent()) {
SQLException sql = (SQLException) sqlEx.get();
System.out.println("Found SQL error: " + sql.getMessage());
}
// Find by exception message
Optional<Throwable> connectionError = Throwables.findThrowableInChain(
ex -> ex.getMessage() != null && ex.getMessage().contains("Connection"),
topLevel
);public class DatabaseService {
public void handleDatabaseOperation() {
try {
performDatabaseOperation();
} catch (Exception e) {
analyzeDatabaseException(e);
throw e;
}
}
private void analyzeDatabaseException(Exception e) {
// Look for specific database errors
Optional<Throwable> sqlEx = Throwables.findThrowableInChain(
ex -> ex instanceof SQLException,
e
);
if (sqlEx.isPresent()) {
SQLException sql = (SQLException) sqlEx.get();
logDatabaseError(sql.getErrorCode(), sql.getSQLState(), sql.getMessage());
}
// Look for connection-related errors
Optional<Throwable> connectionEx = Throwables.findThrowableInChain(
ex -> ex.getMessage() != null &&
(ex.getMessage().contains("connection") ||
ex.getMessage().contains("Connection")),
e
);
if (connectionEx.isPresent()) {
alertConnectionIssue(connectionEx.get().getMessage());
}
}
}public class RetryableService {
public void performWithRetry() {
int maxRetries = 3;
int attempt = 0;
while (attempt < maxRetries) {
try {
performOperation();
return; // Success
} catch (Exception e) {
if (shouldRetry(e)) {
attempt++;
if (attempt >= maxRetries) {
throw new RuntimeException("Max retries exceeded", e);
}
try {
Thread.sleep(1000 * attempt); // Exponential backoff
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted during retry", ie);
}
} else {
throw e; // Don't retry
}
}
}
}
private boolean shouldRetry(Exception e) {
// Retry on temporary network issues
Optional<Throwable> networkError = Throwables.findThrowableInChain(
ex -> ex instanceof SocketTimeoutException ||
ex instanceof ConnectException ||
(ex.getMessage() != null && ex.getMessage().contains("timeout")),
e
);
if (networkError.isPresent()) {
return true;
}
// Don't retry on authentication/authorization issues
Optional<Throwable> authError = Throwables.findThrowableInChain(
ex -> ex instanceof SecurityException ||
(ex.getMessage() != null &&
(ex.getMessage().contains("authentication") ||
ex.getMessage().contains("authorization"))),
e
);
return authError.isEmpty(); // Retry only if no auth error found
}
}public class ExceptionAnalyzer {
private static final Logger logger = LoggerFactory.getLogger(ExceptionAnalyzer.class);
public void analyzeAndLog(Exception e, String operation) {
// Log the top-level exception
logger.error("Operation failed: {}", operation, e);
// Find and log specific error types with additional context
findAndLogSpecificErrors(e);
// Extract metrics for monitoring
extractMetricsFromException(e, operation);
}
private void findAndLogSpecificErrors(Exception e) {
// Look for timeout issues
Optional<Throwable> timeout = Throwables.findThrowableInChain(
ex -> ex instanceof TimeoutException ||
(ex.getMessage() != null && ex.getMessage().contains("timeout")),
e
);
timeout.ifPresent(ex -> logger.warn("Timeout detected: {}", ex.getMessage()));
// Look for resource issues
Optional<Throwable> resource = Throwables.findThrowableInChain(
ex -> ex instanceof OutOfMemoryError ||
ex instanceof IOException,
e
);
resource.ifPresent(ex -> logger.error("Resource issue: {}", ex.getMessage()));
// Look for configuration issues
Optional<Throwable> config = Throwables.findThrowableInChain(
ex -> ex instanceof IllegalArgumentException ||
ex instanceof IllegalStateException,
e
);
config.ifPresent(ex -> logger.warn("Configuration issue: {}", ex.getMessage()));
}
private void extractMetricsFromException(Exception e, String operation) {
// Count different types of errors for monitoring dashboards
Throwables.findThrowableInChain(ex -> ex instanceof SQLException, e)
.ifPresent(ex -> incrementMetric("database.errors", operation));
Throwables.findThrowableInChain(ex -> ex instanceof SocketTimeoutException, e)
.ifPresent(ex -> incrementMetric("network.timeouts", operation));
Throwables.findThrowableInChain(ex -> ex instanceof SecurityException, e)
.ifPresent(ex -> incrementMetric("security.errors", operation));
}
}try {
URL resource = Resources.getResource("missing-file.txt");
} catch (IllegalArgumentException e) {
// Resource not found
logger.warn("Resource not found: {}", e.getMessage());
// Provide fallback or default behavior
}// findThrowableInChain handles null input gracefully
Exception nullException = null;
Optional<Throwable> result = Throwables.findThrowableInChain(
ex -> ex instanceof IOException,
nullException
);
// result will be Optional.empty(), no exception thrown
// Handles circular reference detection automatically
Exception circular1 = new RuntimeException("Error 1");
Exception circular2 = new RuntimeException("Error 2", circular1);
// Don't do this in real code, but if it happens, the method handles it
// circular1.initCause(circular2); // Would create circular reference
Optional<Throwable> result2 = Throwables.findThrowableInChain(
ex -> ex.getMessage().contains("Error"),
circular1
);
// Method prevents infinite loops by tracking visited exceptionspublic class ConfigurationManager {
public Properties loadConfiguration(String primaryResource, String fallbackResource) {
Properties props = new Properties();
// Try primary resource first
try {
URL primaryUrl = Resources.getResource(primaryResource);
try (InputStream input = primaryUrl.openStream()) {
props.load(input);
return props;
}
} catch (IllegalArgumentException e) {
logger.info("Primary config not found: {}, trying fallback", primaryResource);
} catch (IOException e) {
logger.warn("Failed to load primary config: {}", primaryResource, e);
}
// Fallback to secondary resource
try {
URL fallbackUrl = Resources.getResource(fallbackResource);
try (InputStream input = fallbackUrl.openStream()) {
props.load(input);
return props;
}
} catch (Exception e) {
throw new RuntimeException("Cannot load configuration from either primary or fallback resource", e);
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-io-dropwizard--dropwizard-util