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

jar-executor.mddocs/

0

# JAR Location and Executor Services

1

2

Utilities for JAR metadata extraction and direct task execution capabilities.

3

4

## JarLocation Class

5

6

The `JarLocation` class encapsulates the location on the local filesystem of the JAR file in which code is executing and provides access to JAR metadata.

7

8

### Constructor

9

10

```java { .api }

11

public JarLocation(Class<?> klass);

12

```

13

14

Constructs a new JarLocation object to access the code source for the specified class.

15

16

**Parameters:**

17

- `klass` - The class to access the code source from

18

19

### Version Information

20

21

```java { .api }

22

public Optional<String> getVersion();

23

```

24

25

Returns the version of the JAR file containing the provided class.

26

27

**Returns:** An `Optional<String>` containing the implementation version from the JAR manifest, or empty if not available

28

29

**Implementation Details:**

30

- Retrieves version from `Package.getImplementationVersion()`

31

- Returns empty Optional if package information is not available

32

- Version information comes from JAR manifest `Implementation-Version` attribute

33

34

### JAR File Name

35

36

```java { .api }

37

public String toString();

38

```

39

40

Returns the name of the JAR file containing the class.

41

42

**Returns:**

43

- The JAR file name if the class is loaded from a JAR file

44

- `"project.jar"` as a fallback if the JAR name cannot be determined or if running from non-JAR sources (e.g., IDE, exploded directories)

45

46

### Usage Examples

47

48

#### Basic JAR Information

49

50

```java

51

import io.dropwizard.util.JarLocation;

52

import java.util.Optional;

53

54

// Get information about the current application's JAR

55

JarLocation appLocation = new JarLocation(MyApplication.class);

56

String jarName = appLocation.toString();

57

Optional<String> version = appLocation.getVersion();

58

59

System.out.println("Running from JAR: " + jarName);

60

if (version.isPresent()) {

61

System.out.println("Version: " + version.get());

62

} else {

63

System.out.println("Version information not available");

64

}

65

```

66

67

#### Application Startup Information

68

69

```java

70

public class ApplicationInfo {

71

private final JarLocation location;

72

private final String applicationName;

73

74

public ApplicationInfo(Class<?> mainClass, String applicationName) {

75

this.location = new JarLocation(mainClass);

76

this.applicationName = applicationName;

77

}

78

79

public void printStartupInfo() {

80

System.out.println("=== " + applicationName + " ===");

81

System.out.println("JAR: " + location.toString());

82

83

Optional<String> version = location.getVersion();

84

if (version.isPresent()) {

85

System.out.println("Version: " + version.get());

86

} else {

87

System.out.println("Version: Development");

88

}

89

90

System.out.println("Java: " + System.getProperty("java.version"));

91

System.out.println("Started at: " + new java.util.Date());

92

}

93

}

94

95

// Usage in main method

96

public class MyApplication {

97

public static void main(String[] args) {

98

ApplicationInfo info = new ApplicationInfo(MyApplication.class, "My Service");

99

info.printStartupInfo();

100

101

// Continue with application startup...

102

}

103

}

104

```

105

106

#### Health Check Integration

107

108

```java

109

public class ApplicationHealthCheck {

110

private final JarLocation jarLocation;

111

112

public ApplicationHealthCheck(Class<?> applicationClass) {

113

this.jarLocation = new JarLocation(applicationClass);

114

}

115

116

public Map<String, Object> getHealthInfo() {

117

Map<String, Object> health = new HashMap<>();

118

health.put("status", "UP");

119

health.put("jar", jarLocation.toString());

120

121

Optional<String> version = jarLocation.getVersion();

122

health.put("version", version.orElse("unknown"));

123

124

return health;

125

}

126

}

127

```

128

129

#### Logging and Monitoring

130

131

```java

132

public class ApplicationMetrics {

133

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

134

135

public static void logApplicationStart(Class<?> mainClass) {

136

JarLocation location = new JarLocation(mainClass);

137

138

logger.info("Application starting - JAR: {}, Version: {}",

139

location.toString(),

140

location.getVersion().orElse("development"));

141

142

// Send metrics to monitoring system

143

sendMetric("app.start", Map.of(

144

"jar", location.toString(),

145

"version", location.getVersion().orElse("dev")

146

));

147

}

148

}

149

```

150

151

## DirectExecutorService Class

152

153

The `DirectExecutorService` is an implementation of `ExecutorService` that directly executes tasks on the calling thread if the service has not been shut down.

154

155

### Constructor

156

157

```java { .api }

158

public DirectExecutorService();

159

```

160

161

Creates a new DirectExecutorService instance.

162

163

### Execution Methods

164

165

```java { .api }

166

public void execute(Runnable command);

167

```

168

169

Executes the given command directly on the calling thread.

170

171

**Parameters:**

172

- `command` - The runnable task to execute

173

174

**Throws:**

175

- `RejectedExecutionException` - If the executor has been shut down

176

177

**Behavior:**

178

- Executes the task immediately on the calling thread

179

- Tracks running tasks for proper shutdown behavior

180

- Rejects new tasks if the executor has been shut down

181

182

### Lifecycle Methods

183

184

```java { .api }

185

public void shutdown();

186

public List<Runnable> shutdownNow();

187

public boolean isShutdown();

188

public boolean isTerminated();

189

public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

190

```

191

192

**shutdown()**: Initiates an orderly shutdown where previously submitted tasks continue to execute, but no new tasks are accepted.

193

194

**shutdownNow()**: Attempts to stop all actively executing tasks and returns an empty list (since tasks execute immediately, there are no queued tasks to return).

195

196

**isShutdown()**: Returns `true` if this executor has been shut down.

197

198

**isTerminated()**: Returns `true` if all tasks have completed following shut down and no tasks are currently running.

199

200

**awaitTermination()**: Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted.

201

202

### Usage Examples

203

204

#### Basic Task Execution

205

206

```java

207

import io.dropwizard.util.DirectExecutorService;

208

import java.util.concurrent.ExecutorService;

209

210

// Create executor

211

ExecutorService executor = new DirectExecutorService();

212

213

// Execute tasks (runs immediately on calling thread)

214

executor.execute(() -> System.out.println("Task 1 executed"));

215

executor.execute(() -> System.out.println("Task 2 executed"));

216

executor.execute(() -> {

217

System.out.println("Task 3 starting");

218

// Some work...

219

System.out.println("Task 3 completed");

220

});

221

222

// Output appears immediately as tasks execute on calling thread

223

// Shutdown when done

224

executor.shutdown();

225

```

226

227

#### Testing and Synchronous Execution

228

229

```java

230

public class TaskProcessor {

231

private final ExecutorService executor;

232

233

public TaskProcessor(ExecutorService executor) {

234

this.executor = executor;

235

}

236

237

public void processItems(List<String> items) {

238

for (String item : items) {

239

executor.execute(() -> processItem(item));

240

}

241

}

242

243

private void processItem(String item) {

244

// Process the item

245

System.out.println("Processing: " + item);

246

}

247

}

248

249

// In tests, use DirectExecutorService for synchronous execution

250

@Test

251

public void testProcessItems() {

252

DirectExecutorService directExecutor = new DirectExecutorService();

253

TaskProcessor processor = new TaskProcessor(directExecutor);

254

255

List<String> items = Arrays.asList("item1", "item2", "item3");

256

processor.processItems(items);

257

258

// All tasks have completed synchronously by this point

259

// No need to wait for async completion in tests

260

261

directExecutor.shutdown();

262

}

263

264

// In production, use a proper thread pool

265

@Component

266

public class ProductionTaskProcessor {

267

@Bean

268

public TaskProcessor taskProcessor() {

269

ExecutorService threadPool = Executors.newFixedThreadPool(10);

270

return new TaskProcessor(threadPool);

271

}

272

}

273

```

274

275

#### Configuration-Driven Executor Selection

276

277

```java

278

public class ExecutorFactory {

279

public enum ExecutionMode {

280

DIRECT, // Use DirectExecutorService

281

ASYNC, // Use thread pool

282

FORK_JOIN // Use ForkJoinPool

283

}

284

285

public ExecutorService createExecutor(ExecutionMode mode, int threadCount) {

286

switch (mode) {

287

case DIRECT:

288

return new DirectExecutorService();

289

case ASYNC:

290

return Executors.newFixedThreadPool(threadCount);

291

case FORK_JOIN:

292

return new ForkJoinPool(threadCount);

293

default:

294

throw new IllegalArgumentException("Unknown execution mode: " + mode);

295

}

296

}

297

}

298

299

// Usage in configuration

300

public class ServiceConfiguration {

301

private ExecutionMode executionMode = ExecutionMode.ASYNC;

302

private int threadCount = 10;

303

304

public ExecutorService createExecutor() {

305

ExecutorFactory factory = new ExecutorFactory();

306

return factory.createExecutor(executionMode, threadCount);

307

}

308

}

309

```

310

311

#### Graceful Shutdown

312

313

```java

314

public class ManagedExecutorService {

315

private final DirectExecutorService executor;

316

private volatile boolean shutdownRequested = false;

317

318

public ManagedExecutorService() {

319

this.executor = new DirectExecutorService();

320

}

321

322

public void executeTask(Runnable task) {

323

if (shutdownRequested) {

324

throw new IllegalStateException("Service is shutting down");

325

}

326

327

executor.execute(task);

328

}

329

330

public void shutdown() {

331

shutdownRequested = true;

332

executor.shutdown();

333

}

334

335

public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {

336

return executor.awaitTermination(timeout, unit);

337

}

338

339

public void shutdownAndWait(long timeoutSeconds) {

340

shutdown();

341

342

try {

343

boolean terminated = awaitTermination(timeoutSeconds, TimeUnit.SECONDS);

344

if (!terminated) {

345

System.err.println("Executor did not terminate within " + timeoutSeconds + " seconds");

346

executor.shutdownNow();

347

}

348

} catch (InterruptedException e) {

349

Thread.currentThread().interrupt();

350

executor.shutdownNow();

351

}

352

}

353

}

354

```

355

356

#### Development vs Production Patterns

357

358

```java

359

public class ServiceManager {

360

private final ExecutorService executor;

361

private final boolean isDevelopment;

362

363

public ServiceManager(boolean isDevelopment) {

364

this.isDevelopment = isDevelopment;

365

366

if (isDevelopment) {

367

// Use DirectExecutorService for easier debugging

368

this.executor = new DirectExecutorService();

369

} else {

370

// Use proper thread pool for production

371

this.executor = Executors.newCachedThreadPool();

372

}

373

}

374

375

public void submitTask(Runnable task) {

376

executor.execute(task);

377

}

378

379

public void shutdown() {

380

executor.shutdown();

381

382

if (!isDevelopment) {

383

// Only need to wait for async executors

384

try {

385

if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {

386

executor.shutdownNow();

387

}

388

} catch (InterruptedException e) {

389

executor.shutdownNow();

390

Thread.currentThread().interrupt();

391

}

392

}

393

}

394

}

395

```

396

397

## Integration Patterns

398

399

### JAR Location in Dropwizard Applications

400

401

```java

402

public class DropwizardApplication extends Application<MyConfiguration> {

403

404

@Override

405

public void run(MyConfiguration configuration, Environment environment) throws Exception {

406

// Log application info at startup

407

JarLocation location = new JarLocation(getClass());

408

log.info("Starting {} from JAR: {}, Version: {}",

409

getName(),

410

location.toString(),

411

location.getVersion().orElse("development"));

412

413

// Add version info to health checks

414

environment.healthChecks().register("version", new HealthCheck() {

415

@Override

416

protected Result check() throws Exception {

417

return Result.healthy("Version: " + location.getVersion().orElse("dev"));

418

}

419

});

420

421

// Add version endpoint

422

environment.jersey().register(new VersionResource(location));

423

}

424

}

425

426

@Path("/version")

427

public class VersionResource {

428

private final JarLocation jarLocation;

429

430

public VersionResource(JarLocation jarLocation) {

431

this.jarLocation = jarLocation;

432

}

433

434

@GET

435

public Map<String, String> getVersion() {

436

return Map.of(

437

"jar", jarLocation.toString(),

438

"version", jarLocation.getVersion().orElse("development")

439

);

440

}

441

}

442

```

443

444

### DirectExecutorService in Testing Framework

445

446

```java

447

public class TestExecutorExtension implements BeforeEachCallback, AfterEachCallback {

448

private DirectExecutorService executor;

449

450

@Override

451

public void beforeEach(ExtensionContext context) {

452

executor = new DirectExecutorService();

453

// Store in test context for injection

454

context.getStore(ExtensionContext.Namespace.GLOBAL)

455

.put("executor", executor);

456

}

457

458

@Override

459

public void afterEach(ExtensionContext context) {

460

if (executor != null) {

461

executor.shutdown();

462

}

463

}

464

465

public static DirectExecutorService getExecutor(ExtensionContext context) {

466

return context.getStore(ExtensionContext.Namespace.GLOBAL)

467

.get("executor", DirectExecutorService.class);

468

}

469

}

470

```