or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-system.mdconfiguration.mddev-mode.mdindex.mdpackaging.mdutilities.md

packaging.mddocs/

0

# Packaging

1

2

Quarkus packaging system handles the creation of various deployment artifacts including JAR files, native executables, container images, and specialized package formats. The packaging infrastructure supports multiple output formats optimized for different deployment scenarios from traditional JVM deployments to cloud-native container environments.

3

4

## Core Imports

5

6

```java

7

// Package configuration

8

import io.quarkus.deployment.pkg.PackageConfig;

9

import io.quarkus.deployment.pkg.NativeConfig;

10

import io.quarkus.deployment.pkg.JarConfig;

11

12

// Package build items

13

import io.quarkus.deployment.pkg.builditem.JarBuildItem;

14

import io.quarkus.deployment.pkg.builditem.NativeImageBuildItem;

15

import io.quarkus.deployment.pkg.builditem.UberJarBuildItem;

16

import io.quarkus.deployment.pkg.builditem.AppCDSBuildItem;

17

import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;

18

import io.quarkus.deployment.pkg.builditem.ProcessInheritIODisabled;

19

20

// Package build steps

21

import io.quarkus.deployment.pkg.steps.JarResultBuildStep;

22

import io.quarkus.deployment.pkg.steps.NativeImageBuildStep;

23

import io.quarkus.deployment.pkg.steps.UberJarBuildStep;

24

import io.quarkus.deployment.pkg.steps.AppCDSBuildStep;

25

26

// Native image configuration

27

import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;

28

import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;

29

import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;

30

import io.quarkus.deployment.builditem.nativeimage.NativeImageConfigBuildItem;

31

32

// Container and SBOM

33

import io.quarkus.deployment.images.ImageConfig;

34

import io.quarkus.deployment.sbom.SbomConfig;

35

```

36

37

## Package Configuration

38

39

### PackageConfig

40

41

Central configuration for application packaging options.

42

43

```java { .api }

44

class PackageConfig {

45

/**

46

* Package type to create

47

*/

48

@WithDefault("jar")

49

PackageType type;

50

51

/**

52

* Output file name (without extension)

53

*/

54

Optional<String> outputName;

55

56

/**

57

* Output directory for package

58

*/

59

@WithDefault("target")

60

String outputDirectory;

61

62

/**

63

* Whether to create AppCDS archive

64

*/

65

@WithDefault("true")

66

boolean createAppcds;

67

68

/**

69

* AppCDS configuration

70

*/

71

AppcdsConfig appcds;

72

73

/**

74

* Whether to add runner suffix to JAR name

75

*/

76

@WithDefault("true")

77

boolean addRunnerSuffix;

78

79

/**

80

* JAR compression configuration

81

*/

82

JarConfig jar;

83

84

/**

85

* Package types supported by Quarkus

86

*/

87

enum PackageType {

88

/**

89

* Standard runnable JAR with dependencies in lib/ folder

90

*/

91

JAR,

92

93

/**

94

* Legacy JAR format (deprecated)

95

*/

96

LEGACY_JAR,

97

98

/**

99

* Fast JAR with optimized startup (default)

100

*/

101

FAST_JAR,

102

103

/**

104

* GraalVM native executable

105

*/

106

NATIVE,

107

108

/**

109

* Native sources for offline compilation

110

*/

111

NATIVE_SOURCES,

112

113

/**

114

* Single JAR with all dependencies included

115

*/

116

UBER_JAR,

117

118

/**

119

* JAR optimized for mutable content updates

120

*/

121

MUTABLE_JAR

122

}

123

}

124

```

125

126

### JarConfig

127

128

Configuration specific to JAR packaging.

129

130

```java { .api }

131

class JarConfig {

132

/**

133

* Compression level for JAR entries (0-9)

134

*/

135

@WithDefault("6")

136

int compressionLevel;

137

138

/**

139

* Whether to compress JAR entries

140

*/

141

@WithDefault("true")

142

boolean compress;

143

144

/**

145

* Manifest attributes to add

146

*/

147

Map<String, String> manifestAttributes;

148

149

/**

150

* Whether to include dependency list in manifest

151

*/

152

@WithDefault("true")

153

boolean addDependencyList;

154

155

/**

156

* User attributes in manifest

157

*/

158

Map<String, String> userConfiguredAttributes;

159

}

160

```

161

162

**Usage Examples:**

163

164

```java

165

// Configuration in application.properties

166

// quarkus.package.type=native

167

// quarkus.package.output-name=my-app

168

// quarkus.package.jar.compress=false

169

170

@BuildStep

171

void configurePackaging(PackageConfig packageConfig,

172

BuildProducer<PackageTypeBuildItem> packageType) {

173

174

packageType.produce(new PackageTypeBuildItem(packageConfig.type));

175

176

if (packageConfig.type == PackageType.UBER_JAR) {

177

// Additional uber JAR configuration

178

setupUberJarPackaging();

179

}

180

}

181

```

182

183

## JAR Packaging

184

185

### JarBuildItem

186

187

Represents the built application JAR with metadata and dependencies.

188

189

```java { .api }

190

class JarBuildItem extends SimpleBuildItem {

191

/**

192

* Path to the built JAR file

193

*/

194

Path getPath();

195

196

/**

197

* Original path before any transformations

198

*/

199

Optional<Path> getOriginalPath();

200

201

/**

202

* Package type of this JAR

203

*/

204

PackageType getType();

205

206

/**

207

* Path to the library directory (for JAR/FAST_JAR types)

208

*/

209

Optional<Path> getLibraryDir();

210

211

/**

212

* Main class specified in the JAR manifest

213

*/

214

Optional<String> getMainClass();

215

216

/**

217

* Class path entries for this JAR

218

*/

219

List<String> getClassPath();

220

}

221

```

222

223

### UberJarBuildItem

224

225

Represents an uber JAR containing all dependencies.

226

227

```java { .api }

228

class UberJarBuildItem extends SimpleBuildItem {

229

/**

230

* Path to the uber JAR file

231

*/

232

Path getPath();

233

234

/**

235

* Original JAR path before uber JAR creation

236

*/

237

Path getOriginalJarPath();

238

239

/**

240

* Size of the uber JAR in bytes

241

*/

242

long getFileSize();

243

}

244

```

245

246

**Usage Examples:**

247

248

```java

249

@BuildStep

250

void buildJar(ApplicationArchivesBuildItem archives,

251

PackageConfig packageConfig,

252

MainClassBuildItem mainClass,

253

BuildProducer<JarBuildItem> jarProducer) throws IOException {

254

255

Path outputDir = Paths.get(packageConfig.outputDirectory);

256

String jarName = determineJarName(packageConfig, mainClass);

257

Path jarPath = outputDir.resolve(jarName + ".jar");

258

259

// Create JAR with manifest and dependencies

260

try (JarBuilder jarBuilder = new JarBuilder(jarPath)) {

261

// Add manifest

262

jarBuilder.addManifest(createManifest(mainClass.getClassName()));

263

264

// Add application classes

265

addApplicationClasses(jarBuilder, archives.getRootArchive());

266

267

// Handle dependencies based on package type

268

if (packageConfig.type == PackageType.FAST_JAR) {

269

Path libDir = setupLibraryDirectory(outputDir);

270

copyDependencies(archives.getApplicationArchives(), libDir);

271

jarProducer.produce(new JarBuildItem(jarPath, packageConfig.type, libDir));

272

} else if (packageConfig.type == PackageType.UBER_JAR) {

273

addDependenciesToJar(jarBuilder, archives.getApplicationArchives());

274

jarProducer.produce(new JarBuildItem(jarPath, packageConfig.type));

275

}

276

}

277

}

278

279

@BuildStep(onlyIf = UberJarRequested.class)

280

UberJarBuildItem createUberJar(JarBuildItem jar,

281

ApplicationArchivesBuildItem archives) throws IOException {

282

283

Path originalJar = jar.getPath();

284

Path uberJarPath = originalJar.getParent()

285

.resolve(originalJar.getFileName().toString().replace(".jar", "-uber.jar"));

286

287

try (JarBuilder uberBuilder = new JarBuilder(uberJarPath)) {

288

// Copy original JAR contents

289

addJarContents(uberBuilder, originalJar);

290

291

// Add all dependencies

292

for (ApplicationArchive archive : archives.getApplicationArchives()) {

293

addArchiveContents(uberBuilder, archive);

294

}

295

}

296

297

return new UberJarBuildItem(uberJarPath, originalJar, Files.size(uberJarPath));

298

}

299

```

300

301

## Native Image Packaging

302

303

### NativeConfig

304

305

Configuration for GraalVM native image compilation.

306

307

```java { .api }

308

class NativeConfig {

309

/**

310

* Whether native image building is enabled

311

*/

312

@WithDefault("false")

313

boolean enabled;

314

315

/**

316

* Additional build arguments for native-image

317

*/

318

List<String> additionalBuildArgs;

319

320

/**

321

* Container image to use for building native image

322

*/

323

@WithDefault("quay.io/quarkus/ubi-quarkus-mandrel-builder-image")

324

String builderImage;

325

326

/**

327

* Container runtime to use for building

328

*/

329

ContainerRuntimeConfig containerRuntime;

330

331

/**

332

* GraalVM installation directory

333

*/

334

Optional<String> graalvmHome;

335

336

/**

337

* Java version for native image

338

*/

339

Optional<String> javaHome;

340

341

/**

342

* Whether to enable debug info in native image

343

*/

344

@WithDefault("false")

345

boolean debug;

346

347

/**

348

* Whether to publish debug info separately

349

*/

350

@WithDefault("false")

351

boolean publishDebugBuildInfo;

352

353

/**

354

* Native image name

355

*/

356

Optional<String> outputName;

357

358

/**

359

* Auto service loader registration

360

*/

361

@WithDefault("false")

362

boolean autoServiceLoaderRegistration;

363

364

/**

365

* Dump generated files during build

366

*/

367

@WithDefault("false")

368

boolean dumpProxies;

369

370

/**

371

* Enable all character sets

372

*/

373

@WithDefault("false")

374

boolean enableAllCharsets;

375

376

/**

377

* Resource configuration files

378

*/

379

List<String> resourceConfigFiles;

380

}

381

```

382

383

### NativeImageBuildItem

384

385

Represents the built native executable.

386

387

```java { .api }

388

class NativeImageBuildItem extends SimpleBuildItem {

389

/**

390

* Path to the native executable

391

*/

392

Path getPath();

393

394

/**

395

* Size of the native executable in bytes

396

*/

397

long getFileSize();

398

399

/**

400

* GraalVM version used for compilation

401

*/

402

Optional<String> getGraalVMVersion();

403

404

/**

405

* Build time in milliseconds

406

*/

407

long getBuildTime();

408

409

/**

410

* Debug symbols file if generated

411

*/

412

Optional<Path> getDebugSymbolsPath();

413

}

414

```

415

416

### Native Image Configuration Build Items

417

418

```java { .api }

419

class ReflectiveClassBuildItem extends MultiBuildItem {

420

/**

421

* Register class for reflection

422

*/

423

static Builder builder(String... classNames);

424

static Builder builder(Class<?>... classes);

425

426

String getClassName();

427

boolean isConstructors();

428

boolean isMethods();

429

boolean isFields();

430

boolean isWeak();

431

432

static class Builder {

433

Builder constructors();

434

Builder constructors(boolean constructors);

435

Builder methods();

436

Builder methods(boolean methods);

437

Builder fields();

438

Builder fields(boolean fields);

439

Builder weak();

440

Builder weak(boolean weak);

441

ReflectiveClassBuildItem build();

442

}

443

}

444

445

class NativeImageResourceBuildItem extends MultiBuildItem {

446

/**

447

* Include resources in native image

448

*/

449

NativeImageResourceBuildItem(String... resources);

450

NativeImageResourceBuildItem(List<String> resources);

451

452

List<String> getResources();

453

}

454

455

class RuntimeInitializedClassBuildItem extends MultiBuildItem {

456

/**

457

* Initialize class at runtime (not build time)

458

*/

459

RuntimeInitializedClassBuildItem(String className);

460

RuntimeInitializedClassBuildItem(Class<?> clazz);

461

462

String getClassName();

463

}

464

465

class JniRuntimeAccessBuildItem extends MultiBuildItem {

466

/**

467

* Enable JNI runtime access for classes

468

*/

469

static Builder builder(String className);

470

static Builder builder(Class<?> clazz);

471

472

String getClassName();

473

boolean isConstructors();

474

boolean isMethods();

475

boolean isFields();

476

477

static class Builder {

478

Builder constructors();

479

Builder methods();

480

Builder fields();

481

JniRuntimeAccessBuildItem build();

482

}

483

}

484

```

485

486

**Usage Examples:**

487

488

```java

489

@BuildStep

490

void configureReflection(BuildProducer<ReflectiveClassBuildItem> reflection) {

491

// Register classes for reflection

492

reflection.produce(ReflectiveClassBuildItem.builder(

493

"com.example.MyClass",

494

"com.example.MyOtherClass"

495

).constructors().methods().fields().build());

496

497

// Register weak reflection (won't fail if class is missing)

498

reflection.produce(ReflectiveClassBuildItem.builder("optional.Class")

499

.weak().build());

500

}

501

502

@BuildStep

503

void configureNativeResources(BuildProducer<NativeImageResourceBuildItem> resources) {

504

// Include properties files

505

resources.produce(new NativeImageResourceBuildItem(

506

"application.properties",

507

"META-INF/services/*"

508

));

509

510

// Include templates and web resources

511

resources.produce(new NativeImageResourceBuildItem("templates/", "static/"));

512

}

513

514

@BuildStep

515

void configureRuntimeInit(BuildProducer<RuntimeInitializedClassBuildItem> runtimeInit) {

516

// Classes that must be initialized at runtime

517

runtimeInit.produce(new RuntimeInitializedClassBuildItem("java.util.Random"));

518

runtimeInit.produce(new RuntimeInitializedClassBuildItem("com.sun.crypto.provider.SunJCE"));

519

}

520

521

@BuildStep(onlyIf = NativeOrNativeSourcesBuild.class)

522

NativeImageBuildItem buildNative(JarBuildItem jar,

523

NativeConfig nativeConfig,

524

List<ReflectiveClassBuildItem> reflectiveClasses,

525

List<NativeImageResourceBuildItem> resources) throws IOException {

526

527

List<String> args = new ArrayList<>();

528

args.add("-jar");

529

args.add(jar.getPath().toString());

530

531

// Add reflection configuration

532

generateReflectionConfig(reflectiveClasses);

533

args.add("-H:ReflectionConfigurationFiles=reflection-config.json");

534

535

// Add resource configuration

536

generateResourceConfig(resources);

537

args.add("-H:ResourceConfigurationFiles=resource-config.json");

538

539

// Add user-provided arguments

540

args.addAll(nativeConfig.additionalBuildArgs);

541

542

// Determine output path

543

Path outputPath = determineNativeImagePath(jar, nativeConfig);

544

args.add("-o");

545

args.add(outputPath.toString());

546

547

// Execute native-image compiler

548

long startTime = System.currentTimeMillis();

549

executeNativeImageBuild(args);

550

long buildTime = System.currentTimeMillis() - startTime;

551

552

return new NativeImageBuildItem(outputPath, Files.size(outputPath), buildTime);

553

}

554

```

555

556

## Container Integration

557

558

### Container Runtime Configuration

559

560

```java { .api }

561

class ContainerRuntimeConfig {

562

/**

563

* Container runtime to use (docker, podman)

564

*/

565

Optional<String> executable;

566

567

/**

568

* Additional options for container runtime

569

*/

570

List<String> options;

571

572

/**

573

* Working directory in container

574

*/

575

@WithDefault("/project")

576

String workingDirectory;

577

}

578

```

579

580

### Image Configuration

581

582

```java { .api }

583

class ImageConfig {

584

/**

585

* Base image for application container

586

*/

587

@WithDefault("registry.access.redhat.com/ubi8/openjdk-17-runtime")

588

String baseJvmImage;

589

590

/**

591

* Base image for native application container

592

*/

593

@WithDefault("registry.access.redhat.com/ubi8/ubi-minimal")

594

String baseNativeImage;

595

596

/**

597

* Additional JVM arguments for containerized app

598

*/

599

List<String> jvmArguments;

600

601

/**

602

* Additional arguments for native app

603

*/

604

List<String> arguments;

605

606

/**

607

* Working directory in container

608

*/

609

@WithDefault("/work/")

610

String workingDirectory;

611

612

/**

613

* User to run as in container

614

*/

615

@WithDefault("1001")

616

String user;

617

618

/**

619

* Exposed ports

620

*/

621

List<Integer> ports;

622

623

/**

624

* Environment variables

625

*/

626

Map<String, String> env;

627

628

/**

629

* Labels to add to container

630

*/

631

Map<String, String> labels;

632

}

633

```

634

635

**Usage Example:**

636

637

```java

638

@BuildStep(onlyIf = ContainerImageRequested.class)

639

void buildContainerImage(JarBuildItem jar,

640

Optional<NativeImageBuildItem> nativeImage,

641

ImageConfig imageConfig,

642

BuildProducer<ContainerImageBuildItem> containerImage) {

643

644

ContainerImageBuilder builder = new ContainerImageBuilder();

645

646

if (nativeImage.isPresent()) {

647

// Native container image

648

builder.from(imageConfig.baseNativeImage)

649

.copy(nativeImage.get().getPath(), "/application")

650

.workdir(imageConfig.workingDirectory)

651

.user(imageConfig.user)

652

.expose(imageConfig.ports)

653

.env(imageConfig.env)

654

.labels(imageConfig.labels)

655

.cmd("/application");

656

} else {

657

// JVM container image

658

builder.from(imageConfig.baseJvmImage)

659

.copy(jar.getPath(), "/deployments/app.jar");

660

661

if (jar.getLibraryDir().isPresent()) {

662

builder.copy(jar.getLibraryDir().get(), "/deployments/lib/");

663

}

664

665

builder.workdir(imageConfig.workingDirectory)

666

.user(imageConfig.user)

667

.expose(imageConfig.ports)

668

.env(imageConfig.env)

669

.labels(imageConfig.labels)

670

.cmd("java", "-jar", "/deployments/app.jar");

671

}

672

673

Path imagePath = builder.build();

674

containerImage.produce(new ContainerImageBuildItem(imagePath));

675

}

676

```

677

678

## AppCDS Support

679

680

### AppCDS Configuration

681

682

Application Class Data Sharing for faster JVM startup.

683

684

```java { .api }

685

class AppcdsConfig {

686

/**

687

* Whether AppCDS is enabled

688

*/

689

@WithDefault("true")

690

boolean enabled;

691

692

/**

693

* Additional JVM arguments for AppCDS generation

694

*/

695

List<String> builderJvmArgs;

696

697

/**

698

* Whether to use container for AppCDS generation

699

*/

700

@WithDefault("false")

701

boolean useContainer;

702

}

703

704

class AppCDSBuildItem extends SimpleBuildItem {

705

/**

706

* Path to generated AppCDS archive

707

*/

708

Path getAppCDSPath();

709

710

/**

711

* JVM arguments to use AppCDS archive

712

*/

713

List<String> getAppCDSJvmArgs();

714

}

715

```

716

717

**Usage Example:**

718

719

```java

720

@BuildStep(onlyIf = { JvmPackaging.class, AppCDSEnabled.class })

721

AppCDSBuildItem generateAppCDS(JarBuildItem jar,

722

AppcdsConfig appcdsConfig,

723

MainClassBuildItem mainClass) throws IOException {

724

725

Path appCDSPath = jar.getPath().getParent().resolve("app.jsa");

726

727

List<String> args = new ArrayList<>();

728

args.add("-Xshare:dump");

729

args.add("-XX:SharedArchiveFile=" + appCDSPath);

730

args.add("-cp");

731

args.add(buildClassPath(jar));

732

args.addAll(appcdsConfig.builderJvmArgs);

733

args.add(mainClass.getClassName());

734

735

// Generate AppCDS archive

736

executeJava(args);

737

738

List<String> jvmArgs = List.of(

739

"-Xshare:on",

740

"-XX:SharedArchiveFile=" + appCDSPath

741

);

742

743

return new AppCDSBuildItem(appCDSPath, jvmArgs);

744

}

745

```

746

747

## Software Bill of Materials (SBOM)

748

749

### SBOM Configuration and Generation

750

751

```java { .api }

752

class SbomConfig {

753

/**

754

* Whether to generate SBOM

755

*/

756

@WithDefault("false")

757

boolean enabled;

758

759

/**

760

* SBOM format (spdx, cyclonedx)

761

*/

762

@WithDefault("spdx")

763

SbomFormat format;

764

765

/**

766

* Include test dependencies

767

*/

768

@WithDefault("false")

769

boolean includeTestDependencies;

770

771

enum SbomFormat {

772

SPDX, CYCLONEDX

773

}

774

}

775

```

776

777

**Usage Example:**

778

779

```java

780

@BuildStep(onlyIf = SbomEnabled.class)

781

void generateSbom(ApplicationArchivesBuildItem archives,

782

SbomConfig sbomConfig,

783

BuildProducer<GeneratedResourceBuildItem> resources) throws IOException {

784

785

SbomGenerator generator = SbomGenerator.create(sbomConfig.format);

786

787

// Add application information

788

generator.addComponent("application",

789

archives.getRootArchive().getKey().toString(),

790

"1.0.0");

791

792

// Add dependencies

793

for (ApplicationArchive archive : archives.getApplicationArchives()) {

794

ResolvedDependency dep = archive.getResolvedDependency();

795

generator.addDependency(

796

dep.getGroupId() + ":" + dep.getArtifactId(),

797

dep.getVersion(),

798

"library"

799

);

800

}

801

802

// Generate SBOM file

803

String sbomContent = generator.generate();

804

String filename = "sbom." + sbomConfig.format.name().toLowerCase();

805

806

resources.produce(new GeneratedResourceBuildItem(

807

"META-INF/" + filename,

808

sbomContent.getBytes(StandardCharsets.UTF_8)

809

));

810

}

811

```