or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-size.mdduration.mdenum-generics.mdindex.mdjar-executor.mdresource-exception.md

resource-exception.mddocs/

0

# Resource and Exception Utilities

1

2

Utilities for resource loading with context class loader fallback and exception chain analysis tools.

3

4

## Resources Class

5

6

The `Resources` utility class provides helper methods to work with resources using appropriate class loaders.

7

8

### Resource Loading

9

10

```java { .api }

11

public static URL getResource(String resourceName);

12

```

13

14

Returns a URL pointing to the specified resource using intelligent class loader selection.

15

16

**Parameters:**

17

- `resourceName` - The name of the resource to locate

18

19

**Returns:** The URL of the resource

20

21

**Throws:**

22

- `IllegalArgumentException` - If the resource is not found

23

24

**Class Loader Selection:**

25

1. **Context Class Loader**: Uses `Thread.currentThread().getContextClassLoader()` when available

26

2. **Fallback**: Uses `Resources.class.getClassLoader()` if context class loader is `null`

27

28

This approach works correctly in various environments including app servers where different threads may have different class loaders.

29

30

### Usage Examples

31

32

#### Basic Resource Loading

33

34

```java

35

import io.dropwizard.util.Resources;

36

import java.net.URL;

37

import java.io.InputStream;

38

39

// Load a resource from the classpath

40

URL configUrl = Resources.getResource("config/application.yml");

41

URL templateUrl = Resources.getResource("templates/email-template.html");

42

URL imageUrl = Resources.getResource("static/images/logo.png");

43

44

// Convert to InputStream for reading

45

try (InputStream configStream = configUrl.openStream()) {

46

// Read configuration file

47

byte[] configBytes = configStream.readAllBytes();

48

String configContent = new String(configBytes);

49

}

50

```

51

52

#### Configuration File Loading

53

54

```java

55

public class ConfigurationLoader {

56

public Properties loadProperties(String resourceName) {

57

try {

58

URL resourceUrl = Resources.getResource(resourceName);

59

Properties props = new Properties();

60

try (InputStream input = resourceUrl.openStream()) {

61

props.load(input);

62

}

63

return props;

64

} catch (IllegalArgumentException e) {

65

throw new RuntimeException("Configuration file not found: " + resourceName, e);

66

} catch (IOException e) {

67

throw new RuntimeException("Failed to load configuration: " + resourceName, e);

68

}

69

}

70

}

71

72

// Usage

73

ConfigurationLoader loader = new ConfigurationLoader();

74

Properties appProps = loader.loadProperties("application.properties");

75

Properties dbProps = loader.loadProperties("database.properties");

76

```

77

78

#### Template and Asset Loading

79

80

```java

81

public class TemplateService {

82

public String loadTemplate(String templateName) {

83

try {

84

URL templateUrl = Resources.getResource("templates/" + templateName);

85

try (InputStream input = templateUrl.openStream()) {

86

return new String(input.readAllBytes(), StandardCharsets.UTF_8);

87

}

88

} catch (IllegalArgumentException e) {

89

throw new RuntimeException("Template not found: " + templateName, e);

90

} catch (IOException e) {

91

throw new RuntimeException("Failed to read template: " + templateName, e);

92

}

93

}

94

}

95

96

// Usage

97

TemplateService templateService = new TemplateService();

98

String emailTemplate = templateService.loadTemplate("email-notification.html");

99

String reportTemplate = templateService.loadTemplate("monthly-report.html");

100

```

101

102

#### Web Application Context

103

104

```java

105

// In servlet or web application contexts where context class loader

106

// is set appropriately for resource discovery

107

public class WebResourceLoader {

108

public byte[] loadWebAsset(String assetPath) {

109

try {

110

// Resources.getResource will use the context class loader

111

// which is typically set correctly in web applications

112

URL assetUrl = Resources.getResource("static/" + assetPath);

113

try (InputStream input = assetUrl.openStream()) {

114

return input.readAllBytes();

115

}

116

} catch (IllegalArgumentException e) {

117

throw new RuntimeException("Web asset not found: " + assetPath, e);

118

} catch (IOException e) {

119

throw new RuntimeException("Failed to load web asset: " + assetPath, e);

120

}

121

}

122

}

123

```

124

125

## Throwables Class

126

127

The `Throwables` utility class provides helper methods to work with exception objects and exception chains.

128

129

### Exception Chain Search

130

131

```java { .api }

132

public static Optional<Throwable> findThrowableInChain(

133

Predicate<Throwable> condition,

134

Throwable t

135

);

136

```

137

138

Search an exception chain for an exception matching a given condition.

139

140

**Parameters:**

141

- `condition` - The condition predicate to match against each exception in the chain

142

- `t` - The head of the exception chain (can be `null`)

143

144

**Returns:** An `Optional` containing the first matching exception in the chain, or empty if no match found

145

146

**Search Behavior:**

147

- Starts from the head exception and traverses the chain using `getCause()`

148

- Prevents infinite loops by tracking visited exceptions

149

- Returns the first exception that matches the condition

150

- Returns empty `Optional` if no match is found or if the input throwable is `null`

151

152

### Usage Examples

153

154

#### Find Specific Exception Types

155

156

```java

157

import io.dropwizard.util.Throwables;

158

import java.util.Optional;

159

160

// Example exception chain

161

Exception rootCause = new SQLException("Connection failed");

162

Exception cause = new RuntimeException("Database error", rootCause);

163

Exception topLevel = new ServiceException("Service unavailable", cause);

164

165

// Find SQLException in the chain

166

Optional<Throwable> sqlEx = Throwables.findThrowableInChain(

167

ex -> ex instanceof SQLException,

168

topLevel

169

);

170

171

if (sqlEx.isPresent()) {

172

SQLException sql = (SQLException) sqlEx.get();

173

System.out.println("Found SQL error: " + sql.getMessage());

174

}

175

176

// Find by exception message

177

Optional<Throwable> connectionError = Throwables.findThrowableInChain(

178

ex -> ex.getMessage() != null && ex.getMessage().contains("Connection"),

179

topLevel

180

);

181

```

182

183

#### Database Exception Analysis

184

185

```java

186

public class DatabaseService {

187

public void handleDatabaseOperation() {

188

try {

189

performDatabaseOperation();

190

} catch (Exception e) {

191

analyzeDatabaseException(e);

192

throw e;

193

}

194

}

195

196

private void analyzeDatabaseException(Exception e) {

197

// Look for specific database errors

198

Optional<Throwable> sqlEx = Throwables.findThrowableInChain(

199

ex -> ex instanceof SQLException,

200

e

201

);

202

203

if (sqlEx.isPresent()) {

204

SQLException sql = (SQLException) sqlEx.get();

205

logDatabaseError(sql.getErrorCode(), sql.getSQLState(), sql.getMessage());

206

}

207

208

// Look for connection-related errors

209

Optional<Throwable> connectionEx = Throwables.findThrowableInChain(

210

ex -> ex.getMessage() != null &&

211

(ex.getMessage().contains("connection") ||

212

ex.getMessage().contains("Connection")),

213

e

214

);

215

216

if (connectionEx.isPresent()) {

217

alertConnectionIssue(connectionEx.get().getMessage());

218

}

219

}

220

}

221

```

222

223

#### Retry Logic Based on Exception Analysis

224

225

```java

226

public class RetryableService {

227

public void performWithRetry() {

228

int maxRetries = 3;

229

int attempt = 0;

230

231

while (attempt < maxRetries) {

232

try {

233

performOperation();

234

return; // Success

235

} catch (Exception e) {

236

if (shouldRetry(e)) {

237

attempt++;

238

if (attempt >= maxRetries) {

239

throw new RuntimeException("Max retries exceeded", e);

240

}

241

try {

242

Thread.sleep(1000 * attempt); // Exponential backoff

243

} catch (InterruptedException ie) {

244

Thread.currentThread().interrupt();

245

throw new RuntimeException("Interrupted during retry", ie);

246

}

247

} else {

248

throw e; // Don't retry

249

}

250

}

251

}

252

}

253

254

private boolean shouldRetry(Exception e) {

255

// Retry on temporary network issues

256

Optional<Throwable> networkError = Throwables.findThrowableInChain(

257

ex -> ex instanceof SocketTimeoutException ||

258

ex instanceof ConnectException ||

259

(ex.getMessage() != null && ex.getMessage().contains("timeout")),

260

e

261

);

262

263

if (networkError.isPresent()) {

264

return true;

265

}

266

267

// Don't retry on authentication/authorization issues

268

Optional<Throwable> authError = Throwables.findThrowableInChain(

269

ex -> ex instanceof SecurityException ||

270

(ex.getMessage() != null &&

271

(ex.getMessage().contains("authentication") ||

272

ex.getMessage().contains("authorization"))),

273

e

274

);

275

276

return authError.isEmpty(); // Retry only if no auth error found

277

}

278

}

279

```

280

281

#### Exception Logging and Monitoring

282

283

```java

284

public class ExceptionAnalyzer {

285

private static final Logger logger = LoggerFactory.getLogger(ExceptionAnalyzer.class);

286

287

public void analyzeAndLog(Exception e, String operation) {

288

// Log the top-level exception

289

logger.error("Operation failed: {}", operation, e);

290

291

// Find and log specific error types with additional context

292

findAndLogSpecificErrors(e);

293

294

// Extract metrics for monitoring

295

extractMetricsFromException(e, operation);

296

}

297

298

private void findAndLogSpecificErrors(Exception e) {

299

// Look for timeout issues

300

Optional<Throwable> timeout = Throwables.findThrowableInChain(

301

ex -> ex instanceof TimeoutException ||

302

(ex.getMessage() != null && ex.getMessage().contains("timeout")),

303

e

304

);

305

timeout.ifPresent(ex -> logger.warn("Timeout detected: {}", ex.getMessage()));

306

307

// Look for resource issues

308

Optional<Throwable> resource = Throwables.findThrowableInChain(

309

ex -> ex instanceof OutOfMemoryError ||

310

ex instanceof IOException,

311

e

312

);

313

resource.ifPresent(ex -> logger.error("Resource issue: {}", ex.getMessage()));

314

315

// Look for configuration issues

316

Optional<Throwable> config = Throwables.findThrowableInChain(

317

ex -> ex instanceof IllegalArgumentException ||

318

ex instanceof IllegalStateException,

319

e

320

);

321

config.ifPresent(ex -> logger.warn("Configuration issue: {}", ex.getMessage()));

322

}

323

324

private void extractMetricsFromException(Exception e, String operation) {

325

// Count different types of errors for monitoring dashboards

326

Throwables.findThrowableInChain(ex -> ex instanceof SQLException, e)

327

.ifPresent(ex -> incrementMetric("database.errors", operation));

328

329

Throwables.findThrowableInChain(ex -> ex instanceof SocketTimeoutException, e)

330

.ifPresent(ex -> incrementMetric("network.timeouts", operation));

331

332

Throwables.findThrowableInChain(ex -> ex instanceof SecurityException, e)

333

.ifPresent(ex -> incrementMetric("security.errors", operation));

334

}

335

}

336

```

337

338

## Error Handling

339

340

### Resources Error Handling

341

342

```java

343

try {

344

URL resource = Resources.getResource("missing-file.txt");

345

} catch (IllegalArgumentException e) {

346

// Resource not found

347

logger.warn("Resource not found: {}", e.getMessage());

348

// Provide fallback or default behavior

349

}

350

```

351

352

### Throwables Error Handling

353

354

```java

355

// findThrowableInChain handles null input gracefully

356

Exception nullException = null;

357

Optional<Throwable> result = Throwables.findThrowableInChain(

358

ex -> ex instanceof IOException,

359

nullException

360

);

361

// result will be Optional.empty(), no exception thrown

362

363

// Handles circular reference detection automatically

364

Exception circular1 = new RuntimeException("Error 1");

365

Exception circular2 = new RuntimeException("Error 2", circular1);

366

// Don't do this in real code, but if it happens, the method handles it

367

// circular1.initCause(circular2); // Would create circular reference

368

369

Optional<Throwable> result2 = Throwables.findThrowableInChain(

370

ex -> ex.getMessage().contains("Error"),

371

circular1

372

);

373

// Method prevents infinite loops by tracking visited exceptions

374

```

375

376

## Integration Patterns

377

378

### Configuration Loading with Fallbacks

379

380

```java

381

public class ConfigurationManager {

382

public Properties loadConfiguration(String primaryResource, String fallbackResource) {

383

Properties props = new Properties();

384

385

// Try primary resource first

386

try {

387

URL primaryUrl = Resources.getResource(primaryResource);

388

try (InputStream input = primaryUrl.openStream()) {

389

props.load(input);

390

return props;

391

}

392

} catch (IllegalArgumentException e) {

393

logger.info("Primary config not found: {}, trying fallback", primaryResource);

394

} catch (IOException e) {

395

logger.warn("Failed to load primary config: {}", primaryResource, e);

396

}

397

398

// Fallback to secondary resource

399

try {

400

URL fallbackUrl = Resources.getResource(fallbackResource);

401

try (InputStream input = fallbackUrl.openStream()) {

402

props.load(input);

403

return props;

404

}

405

} catch (Exception e) {

406

throw new RuntimeException("Cannot load configuration from either primary or fallback resource", e);

407

}

408

}

409

}

410

```