or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-integration.mdimage-packaging.mdindex.mdjar-writing.mdlaunch-scripts.mdlayer-support.mdlayout-management.mdlibrary-management.mdmain-class-detection.mdrepackaging.md

build-integration.mddocs/

0

# Build Integration

1

2

Utilities for integrating with build tools and generating build metadata for Spring Boot Actuator endpoints. The build integration system provides seamless integration with Maven, Gradle, and other build systems while generating runtime metadata for monitoring and management.

3

4

## Capabilities

5

6

### Build Properties Writer

7

8

Utility class for generating build-info.properties files consumed by Spring Boot Actuator's info endpoint.

9

10

```java { .api }

11

public final class BuildPropertiesWriter {

12

/**

13

* Create a build properties writer for the specified output file.

14

*

15

* @param outputFile the file where build properties will be written

16

*/

17

public BuildPropertiesWriter(File outputFile);

18

19

/**

20

* Write build properties for the given project details.

21

* Creates a properties file compatible with Spring Boot Actuator's info endpoint.

22

*

23

* @param projectDetails the project details to write

24

* @throws IOException if writing fails

25

*/

26

public void writeBuildProperties(ProjectDetails projectDetails) throws IOException;

27

28

/**

29

* Project details containing build metadata.

30

*/

31

public static final class ProjectDetails {

32

// Contains project information like name, version, build time, etc.

33

// Used to generate build-info.properties for actuator endpoints

34

}

35

36

/**

37

* Exception thrown when an additional property has a null value.

38

*/

39

public static class NullAdditionalPropertyValueException extends IllegalArgumentException {

40

public NullAdditionalPropertyValueException(String name);

41

}

42

}

43

```

44

45

### Java Executable

46

47

Utility for locating and working with Java executables in the runtime environment.

48

49

```java { .api }

50

public class JavaExecutable {

51

// Provides access to the Java executable used to run the current process

52

// Useful for spawning Java processes with consistent JVM configuration

53

}

54

```

55

56

### Process Execution

57

58

Utility for running external processes, commonly used for build tool integration and system commands.

59

60

```java { .api }

61

public class RunProcess {

62

/**

63

* Run an external process with the specified arguments.

64

*

65

* @param waitForProcess whether to wait for the process to complete

66

* @param args the command line arguments

67

* @return the process exit code (if waitForProcess is true)

68

* @throws IOException if process execution fails

69

*/

70

public int run(boolean waitForProcess, String... args) throws IOException;

71

}

72

```

73

74

## Usage Examples

75

76

### Basic Build Properties Generation

77

78

```java

79

import org.springframework.boot.loader.tools.BuildPropertiesWriter;

80

import org.springframework.boot.loader.tools.BuildPropertiesWriter.ProjectDetails;

81

import java.io.File;

82

import java.io.IOException;

83

import java.time.Instant;

84

import java.util.Properties;

85

86

// Create build properties for actuator endpoint

87

File outputFile = new File("target/classes/META-INF/build-info.properties");

88

BuildPropertiesWriter writer = new BuildPropertiesWriter(outputFile);

89

90

// Create project details

91

ProjectDetails details = new ProjectDetails() {{

92

setGroup("com.example");

93

setArtifact("myapp");

94

setName("My Application");

95

setVersion("1.0.0");

96

setTime(Instant.now());

97

98

// Add custom build information

99

getAdditional().put("build.user", System.getProperty("user.name"));

100

getAdditional().put("build.java.version", System.getProperty("java.version"));

101

getAdditional().put("build.os", System.getProperty("os.name"));

102

}};

103

104

try {

105

writer.writeBuildProperties(details);

106

System.out.println("Build properties written to: " + outputFile.getAbsolutePath());

107

} catch (IOException e) {

108

System.err.println("Failed to write build properties: " + e.getMessage());

109

}

110

111

// The generated file will be available at /actuator/info endpoint:

112

// {

113

// "build": {

114

// "group": "com.example",

115

// "artifact": "myapp",

116

// "name": "My Application",

117

// "version": "1.0.0",

118

// "time": "2024-01-15T10:30:00.000Z",

119

// "build.user": "developer",

120

// "build.java.version": "17.0.1",

121

// "build.os": "Linux"

122

// }

123

// }

124

```

125

126

### Maven Integration

127

128

```java

129

import org.springframework.boot.loader.tools.*;

130

import java.io.File;

131

import java.io.IOException;

132

import java.time.Instant;

133

import java.util.Properties;

134

135

// Maven plugin integration example

136

public class MavenBuildPropertiesGenerator {

137

138

public void generateBuildProperties(MavenProject project, File outputFile) throws IOException {

139

BuildPropertiesWriter writer = new BuildPropertiesWriter(outputFile);

140

141

ProjectDetails details = new ProjectDetails();

142

details.setGroup(project.getGroupId());

143

details.setArtifact(project.getArtifactId());

144

details.setName(project.getName());

145

details.setVersion(project.getVersion());

146

details.setTime(Instant.now());

147

148

// Add Maven-specific properties

149

Properties additional = details.getAdditional();

150

additional.put("build.maven.version", getMavenVersion());

151

additional.put("build.java.target", project.getProperties().getProperty("maven.compiler.target"));

152

additional.put("build.java.source", project.getProperties().getProperty("maven.compiler.source"));

153

154

// Add SCM information if available

155

if (project.getScm() != null) {

156

additional.put("build.scm.url", project.getScm().getUrl());

157

additional.put("build.scm.connection", project.getScm().getConnection());

158

}

159

160

// Add CI/CD information

161

String buildNumber = System.getenv("BUILD_NUMBER");

162

if (buildNumber != null) {

163

additional.put("build.number", buildNumber);

164

}

165

166

String gitCommit = System.getenv("GIT_COMMIT");

167

if (gitCommit != null) {

168

additional.put("build.git.commit", gitCommit);

169

}

170

171

writer.writeBuildProperties(details);

172

}

173

174

private String getMavenVersion() {

175

// Implementation to get Maven version

176

return "3.8.1";

177

}

178

}

179

```

180

181

### Gradle Integration

182

183

```java

184

import org.springframework.boot.loader.tools.*;

185

import java.io.File;

186

import java.io.IOException;

187

import java.time.Instant;

188

import java.util.Properties;

189

190

// Gradle plugin integration example

191

public class GradleBuildPropertiesGenerator {

192

193

public void generateBuildProperties(String group, String name, String version,

194

File outputFile, Properties gradleProperties) throws IOException {

195

BuildPropertiesWriter writer = new BuildPropertiesWriter(outputFile);

196

197

ProjectDetails details = new ProjectDetails();

198

details.setGroup(group);

199

details.setArtifact(name);

200

details.setName(name);

201

details.setVersion(version);

202

details.setTime(Instant.now());

203

204

// Add Gradle-specific properties

205

Properties additional = details.getAdditional();

206

additional.put("build.gradle.version", getGradleVersion());

207

208

// Add project properties

209

gradleProperties.forEach((key, value) -> {

210

if (key.toString().startsWith("build.")) {

211

additional.put(key.toString(), value.toString());

212

}

213

});

214

215

// Add system information

216

additional.put("build.java.vendor", System.getProperty("java.vendor"));

217

additional.put("build.java.vm.name", System.getProperty("java.vm.name"));

218

219

writer.writeBuildProperties(details);

220

}

221

222

private String getGradleVersion() {

223

// Implementation to get Gradle version

224

return "7.6";

225

}

226

}

227

```

228

229

### Custom Build Information

230

231

```java

232

import org.springframework.boot.loader.tools.*;

233

import java.io.File;

234

import java.io.IOException;

235

import java.time.Instant;

236

import java.time.ZoneId;

237

import java.time.format.DateTimeFormatter;

238

import java.util.Properties;

239

240

// Generate comprehensive build information

241

public class ComprehensiveBuildInfo {

242

243

public void generateBuildInfo(String group, String artifact, String version,

244

File outputFile) throws IOException {

245

BuildPropertiesWriter writer = new BuildPropertiesWriter(outputFile);

246

247

ProjectDetails details = new ProjectDetails();

248

details.setGroup(group);

249

details.setArtifact(artifact);

250

details.setName(artifact);

251

details.setVersion(version);

252

details.setTime(Instant.now());

253

254

Properties additional = details.getAdditional();

255

256

// Build environment

257

additional.put("build.user", System.getProperty("user.name"));

258

additional.put("build.host", getHostname());

259

additional.put("build.time.formatted",

260

DateTimeFormatter.ISO_LOCAL_DATE_TIME

261

.withZone(ZoneId.systemDefault())

262

.format(Instant.now()));

263

264

// Java environment

265

additional.put("build.java.version", System.getProperty("java.version"));

266

additional.put("build.java.vendor", System.getProperty("java.vendor"));

267

additional.put("build.java.home", System.getProperty("java.home"));

268

269

// Operating system

270

additional.put("build.os.name", System.getProperty("os.name"));

271

additional.put("build.os.version", System.getProperty("os.version"));

272

additional.put("build.os.arch", System.getProperty("os.arch"));

273

274

// Runtime information

275

Runtime runtime = Runtime.getRuntime();

276

additional.put("build.runtime.processors", String.valueOf(runtime.availableProcessors()));

277

additional.put("build.runtime.max.memory", String.valueOf(runtime.maxMemory()));

278

279

// Custom application properties

280

additional.put("build.profile", System.getProperty("spring.profiles.active", "default"));

281

additional.put("build.type", "executable-jar");

282

283

try {

284

writer.writeBuildProperties(details);

285

System.out.println("Comprehensive build info written to: " + outputFile);

286

} catch (BuildPropertiesWriter.NullAdditionalPropertyValueException e) {

287

System.err.println("Null value detected for property: " + e.getMessage());

288

throw e;

289

}

290

}

291

292

private String getHostname() {

293

try {

294

return java.net.InetAddress.getLocalHost().getHostName();

295

} catch (Exception e) {

296

return "unknown";

297

}

298

}

299

}

300

```

301

302

### Process Execution for Build Tools

303

304

```java

305

import org.springframework.boot.loader.tools.RunProcess;

306

import java.io.IOException;

307

import java.util.Arrays;

308

309

// Execute build commands and capture results

310

public class BuildToolRunner {

311

private final RunProcess processRunner = new RunProcess();

312

313

public void runMavenBuild(String... goals) throws IOException {

314

String[] command = new String[goals.length + 1];

315

command[0] = "mvn";

316

System.arraycopy(goals, 0, command, 1, goals.length);

317

318

System.out.println("Executing: " + Arrays.toString(command));

319

int exitCode = processRunner.run(true, command);

320

321

if (exitCode != 0) {

322

throw new IOException("Maven build failed with exit code: " + exitCode);

323

}

324

325

System.out.println("Maven build completed successfully");

326

}

327

328

public void runGradleBuild(String... tasks) throws IOException {

329

String[] command = new String[tasks.length + 1];

330

command[0] = "./gradlew";

331

System.arraycopy(tasks, 0, command, 1, tasks.length);

332

333

System.out.println("Executing: " + Arrays.toString(command));

334

int exitCode = processRunner.run(true, command);

335

336

if (exitCode != 0) {

337

throw new IOException("Gradle build failed with exit code: " + exitCode);

338

}

339

340

System.out.println("Gradle build completed successfully");

341

}

342

343

public void runGitCommands() throws IOException {

344

// Get git information for build metadata

345

int exitCode;

346

347

// Get current commit hash

348

exitCode = processRunner.run(true, "git", "rev-parse", "HEAD");

349

if (exitCode != 0) {

350

System.out.println("Warning: Could not get git commit hash");

351

}

352

353

// Get current branch

354

exitCode = processRunner.run(true, "git", "rev-parse", "--abbrev-ref", "HEAD");

355

if (exitCode != 0) {

356

System.out.println("Warning: Could not get git branch");

357

}

358

359

// Check if working directory is clean

360

exitCode = processRunner.run(true, "git", "diff-index", "--quiet", "HEAD", "--");

361

if (exitCode != 0) {

362

System.out.println("Warning: Working directory has uncommitted changes");

363

}

364

}

365

}

366

367

// Usage

368

BuildToolRunner runner = new BuildToolRunner();

369

try {

370

runner.runGitCommands();

371

runner.runMavenBuild("clean", "compile", "test");

372

// or

373

// runner.runGradleBuild("clean", "build");

374

} catch (IOException e) {

375

System.err.println("Build process failed: " + e.getMessage());

376

}

377

```

378

379

### Actuator Integration

380

381

```java

382

import org.springframework.boot.loader.tools.*;

383

import java.io.File;

384

import java.io.IOException;

385

import java.time.Instant;

386

import java.util.Properties;

387

388

// Generate build properties specifically for Spring Boot Actuator

389

public class ActuatorBuildInfoGenerator {

390

391

public void generateForActuator(ProjectDetails projectDetails, File outputFile) throws IOException {

392

// Ensure output directory exists

393

outputFile.getParentFile().mkdirs();

394

395

BuildPropertiesWriter writer = new BuildPropertiesWriter(outputFile);

396

397

// Add actuator-specific properties

398

Properties additional = projectDetails.getAdditional();

399

400

// Health check information

401

additional.put("build.health.check.url", "/actuator/health");

402

additional.put("build.info.url", "/actuator/info");

403

additional.put("build.metrics.url", "/actuator/metrics");

404

405

// Build pipeline information

406

String pipelineId = System.getenv("CI_PIPELINE_ID");

407

if (pipelineId != null) {

408

additional.put("build.pipeline.id", pipelineId);

409

}

410

411

String buildUrl = System.getenv("BUILD_URL");

412

if (buildUrl != null) {

413

additional.put("build.url", buildUrl);

414

}

415

416

// Application configuration

417

additional.put("build.spring.boot.version", getSpringBootVersion());

418

additional.put("build.spring.version", getSpringVersion());

419

420

writer.writeBuildProperties(projectDetails);

421

422

System.out.println("Actuator build info generated: " + outputFile.getAbsolutePath());

423

System.out.println("Available at: /actuator/info");

424

}

425

426

private String getSpringBootVersion() {

427

// Get Spring Boot version from classpath

428

Package pkg = org.springframework.boot.SpringBootVersion.class.getPackage();

429

return pkg != null ? pkg.getImplementationVersion() : "unknown";

430

}

431

432

private String getSpringVersion() {

433

// Get Spring Framework version

434

Package pkg = org.springframework.core.SpringVersion.class.getPackage();

435

return pkg != null ? pkg.getImplementationVersion() : "unknown";

436

}

437

}

438

```

439

440

### Build Properties Validation

441

442

```java

443

import org.springframework.boot.loader.tools.*;

444

import java.io.File;

445

import java.io.FileInputStream;

446

import java.io.IOException;

447

import java.util.Properties;

448

449

// Validate generated build properties

450

public class BuildPropertiesValidator {

451

452

public void validateBuildProperties(File buildPropertiesFile) throws IOException {

453

if (!buildPropertiesFile.exists()) {

454

throw new IOException("Build properties file not found: " + buildPropertiesFile);

455

}

456

457

Properties props = new Properties();

458

try (FileInputStream fis = new FileInputStream(buildPropertiesFile)) {

459

props.load(fis);

460

}

461

462

// Validate required properties

463

validateRequired(props, "build.group", "Build group is required");

464

validateRequired(props, "build.artifact", "Build artifact is required");

465

validateRequired(props, "build.version", "Build version is required");

466

validateRequired(props, "build.time", "Build time is required");

467

468

// Validate property formats

469

validateVersion(props.getProperty("build.version"));

470

validateTime(props.getProperty("build.time"));

471

472

System.out.println("Build properties validation passed");

473

474

// Print summary

475

System.out.println("Build Properties Summary:");

476

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

477

props.forEach((key, value) -> {

478

if (key.toString().startsWith("build.")) {

479

System.out.println(key + " = " + value);

480

}

481

});

482

}

483

484

private void validateRequired(Properties props, String key, String message) throws IOException {

485

if (!props.containsKey(key) || props.getProperty(key).trim().isEmpty()) {

486

throw new IOException(message + ": " + key);

487

}

488

}

489

490

private void validateVersion(String version) throws IOException {

491

if (version == null || !version.matches("\\d+\\.\\d+\\.\\d+.*")) {

492

throw new IOException("Invalid version format: " + version);

493

}

494

}

495

496

private void validateTime(String time) throws IOException {

497

try {

498

Instant.parse(time);

499

} catch (Exception e) {

500

throw new IOException("Invalid build time format: " + time, e);

501

}

502

}

503

}

504

```

505

506

## Integration Patterns

507

508

### Maven Plugin Integration

509

510

```xml

511

<plugin>

512

<groupId>org.springframework.boot</groupId>

513

<artifactId>spring-boot-maven-plugin</artifactId>

514

<version>3.2.0</version>

515

<executions>

516

<execution>

517

<goals>

518

<goal>build-info</goal>

519

</goals>

520

<configuration>

521

<additionalProperties>

522

<build.user>${user.name}</build.user>

523

<build.java.target>${maven.compiler.target}</build.java.target>

524

<build.maven.version>${maven.version}</build.maven.version>

525

</additionalProperties>

526

</configuration>

527

</execution>

528

</executions>

529

</plugin>

530

```

531

532

### Gradle Plugin Integration

533

534

```groovy

535

springBoot {

536

buildInfo {

537

properties {

538

additional = [

539

'build.user': System.getProperty('user.name'),

540

'build.java.target': project.targetCompatibility,

541

'build.gradle.version': gradle.gradleVersion

542

]

543

}

544

}

545

}

546

```

547

548

The build integration system provides comprehensive support for capturing and exposing build metadata, enabling better application monitoring, debugging, and operational visibility through Spring Boot's Actuator endpoints.