or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-operations.mdfunctional-queries.mdindex.mdlegacy-api.mdscanners.mdserialization.mdutilities.md

serialization.mddocs/

0

# Serialization

1

2

Serialization capabilities for saving and loading scanned metadata in multiple formats including XML, JSON, and Java code generation. This enables persistent storage and sharing of metadata across different application runs and environments.

3

4

## Capabilities

5

6

### Serializer Interface

7

8

Base contract for all serialization implementations providing read and write operations.

9

10

```java { .api }

11

/**

12

* Contract for serializing/deserializing Reflections metadata

13

*/

14

interface Serializer {

15

/** Read Reflections metadata from input stream */

16

Reflections read(InputStream inputStream);

17

18

/** Save Reflections metadata to file */

19

File save(Reflections reflections, String filename);

20

21

/** Prepare file with parent directories (static utility) */

22

static File prepareFile(String filename);

23

}

24

```

25

26

### XML Serialization

27

28

XML format serialization for human-readable and widely compatible metadata storage.

29

30

```java { .api }

31

/**

32

* XML serialization format implementation

33

*/

34

class XmlSerializer implements Serializer {

35

/** Default constructor */

36

XmlSerializer();

37

38

/** Read XML metadata from input stream */

39

Reflections read(InputStream inputStream);

40

41

/** Save metadata as XML file */

42

File save(Reflections reflections, String filename);

43

}

44

```

45

46

### JSON Serialization

47

48

JSON format serialization for lightweight and web-friendly metadata storage.

49

50

```java { .api }

51

/**

52

* JSON serialization format implementation

53

*/

54

class JsonSerializer implements Serializer {

55

/** Default constructor */

56

JsonSerializer();

57

58

/** Read JSON metadata from input stream */

59

Reflections read(InputStream inputStream);

60

61

/** Save metadata as JSON file */

62

File save(Reflections reflections, String filename);

63

}

64

```

65

66

### Java Code Generation

67

68

Java source code generation for type-safe compile-time access to metadata.

69

70

```java { .api }

71

/**

72

* Java source code generation for type-safe access

73

*/

74

class JavaCodeSerializer implements Serializer {

75

/** Default constructor */

76

JavaCodeSerializer();

77

78

/** Not supported - throws UnsupportedOperationException */

79

Reflections read(InputStream inputStream);

80

81

/** Generate Java interface source code with type-safe metadata access methods */

82

File save(Reflections reflections, String name);

83

}

84

```

85

86

### Reflections Serialization Methods

87

88

Built-in serialization methods in the main Reflections class for convenient saving and loading.

89

90

```java { .api }

91

/**

92

* Built-in serialization methods in Reflections class

93

*/

94

class Reflections {

95

/** Save metadata to XML file (default serializer) */

96

File save(String filename);

97

98

/** Save metadata to file using specified serializer */

99

File save(String filename, Serializer serializer);

100

101

/** Collect metadata from input stream using specified serializer */

102

Reflections collect(InputStream inputStream, Serializer serializer);

103

104

/** Collect metadata from file using specified serializer */

105

Reflections collect(File file, Serializer serializer);

106

}

107

```

108

109

### Static Collection Methods

110

111

Static methods for collecting pre-saved metadata from various sources and locations.

112

113

```java { .api }

114

/**

115

* Static methods for collecting saved metadata

116

*/

117

class Reflections {

118

/** Collect saved XML metadata from META-INF/reflections/ with default filter */

119

static Reflections collect();

120

121

/** Collect saved metadata with custom package prefix and resource name filter */

122

static Reflections collect(String packagePrefix, Predicate<String> resourceNameFilter);

123

124

/** Collect saved metadata with custom serializer */

125

static Reflections collect(String packagePrefix, Predicate<String> resourceNameFilter, Serializer serializer);

126

}

127

```

128

129

## Usage Examples

130

131

### Basic XML Serialization

132

133

```java

134

import org.reflections.Reflections;

135

import org.reflections.serializers.XmlSerializer;

136

137

// Create and configure Reflections

138

Reflections reflections = new Reflections("com.mycompany");

139

140

// Save to XML using default serializer

141

File xmlFile = reflections.save("target/reflections-metadata.xml");

142

143

// Save to XML using explicit serializer

144

File explicitXmlFile = reflections.save("target/metadata.xml", new XmlSerializer());

145

146

// Load from XML

147

Reflections loadedReflections = new XmlSerializer().read(new FileInputStream(xmlFile));

148

149

// Collect from file

150

Reflections collected = new Reflections().collect(xmlFile, new XmlSerializer());

151

```

152

153

### JSON Serialization

154

155

```java

156

import org.reflections.serializers.JsonSerializer;

157

import java.io.FileInputStream;

158

159

// Save to JSON

160

JsonSerializer jsonSerializer = new JsonSerializer();

161

File jsonFile = reflections.save("target/reflections-metadata.json", jsonSerializer);

162

163

// Load from JSON

164

Reflections fromJson = jsonSerializer.read(new FileInputStream(jsonFile));

165

166

// Merge JSON data with existing Reflections

167

Reflections existing = new Reflections("com.mycompany.core");

168

Reflections merged = existing.collect(jsonFile, jsonSerializer);

169

```

170

171

### Java Code Generation

172

173

```java

174

import org.reflections.serializers.JavaCodeSerializer;

175

176

// Generate Java interface with type-safe access methods

177

JavaCodeSerializer codeSerializer = new JavaCodeSerializer();

178

File javaFile = reflections.save("src/generated/java/ReflectionsMetadata", codeSerializer);

179

180

// This generates a Java interface like:

181

// public interface ReflectionsMetadata {

182

// Set<String> getSubTypesOf_com_mycompany_Service();

183

// Set<String> getTypesAnnotatedWith_org_springframework_stereotype_Component();

184

// // ... other generated methods

185

// }

186

187

// Note: JavaCodeSerializer.read() is not supported and throws UnsupportedOperationException

188

```

189

190

### Collecting Pre-saved Metadata

191

192

```java

193

import org.reflections.util.FilterBuilder;

194

195

// Collect all saved metadata from META-INF/reflections/

196

Reflections collected = Reflections.collect();

197

198

// Collect with package prefix filter

199

Reflections packageFiltered = Reflections.collect("com.mycompany",

200

resourceName -> resourceName.contains("reflections"));

201

202

// Collect with custom resource filter

203

Reflections customFiltered = Reflections.collect("",

204

new FilterBuilder().includePattern(".*-reflections\\.xml")::test);

205

206

// Collect using different serializer

207

Reflections jsonCollected = Reflections.collect("com.mycompany",

208

resourceName -> resourceName.endsWith(".json"),

209

new JsonSerializer());

210

```

211

212

### Build-time Metadata Generation

213

214

```java

215

// Example build-time metadata generation and collection pattern

216

public class MetadataGenerator {

217

public static void main(String[] args) {

218

// Generate metadata during build

219

Reflections buildTimeReflections = new Reflections(new ConfigurationBuilder()

220

.forPackages("com.mycompany")

221

.setScanners(Scanners.values())

222

.filterInputsBy(new FilterBuilder()

223

.includePackage("com.mycompany")

224

.excludePackage("com.mycompany.test")));

225

226

// Save to build output directory

227

buildTimeReflections.save("target/classes/META-INF/reflections/myapp-reflections.xml");

228

229

// Also generate JSON version

230

buildTimeReflections.save("target/classes/META-INF/reflections/myapp-reflections.json",

231

new JsonSerializer());

232

233

// Generate type-safe access code

234

buildTimeReflections.save("src/generated/java/com/mycompany/ReflectionsMetadata",

235

new JavaCodeSerializer());

236

}

237

}

238

239

// Runtime collection (much faster than scanning)

240

public class RuntimeUsage {

241

public void usePreGeneratedMetadata() {

242

// Collect pre-generated metadata at runtime

243

Reflections runtime = Reflections.collect("META-INF/reflections/",

244

name -> name.contains("myapp-reflections"));

245

246

// Use normally - no scanning overhead

247

Set<Class<?>> services = runtime.get(SubTypes.of(Service.class).asClass());

248

}

249

}

250

```

251

252

### Serialization Configuration and Customization

253

254

```java

255

// Custom serialization workflow

256

public class CustomSerializationWorkflow {

257

258

public void saveMultipleFormats(Reflections reflections, String baseName) {

259

// Save in multiple formats

260

reflections.save(baseName + ".xml", new XmlSerializer());

261

reflections.save(baseName + ".json", new JsonSerializer());

262

263

try {

264

reflections.save(baseName + ".java", new JavaCodeSerializer());

265

} catch (UnsupportedOperationException e) {

266

// Handle JavaCodeSerializer read limitation

267

System.out.println("Java code generation completed, read not supported");

268

}

269

}

270

271

public Reflections loadFromMultipleSources() {

272

Reflections combined = new Reflections();

273

274

// Load and merge from different sources

275

try {

276

combined.merge(new XmlSerializer().read(

277

new FileInputStream("metadata1.xml")));

278

} catch (FileNotFoundException e) {

279

// Handle missing file

280

}

281

282

try {

283

combined.merge(new JsonSerializer().read(

284

new FileInputStream("metadata2.json")));

285

} catch (FileNotFoundException e) {

286

// Handle missing file

287

}

288

289

return combined;

290

}

291

}

292

```

293

294

### Performance Optimization with Serialization

295

296

```java

297

// Optimized metadata loading pattern

298

public class OptimizedMetadataLoading {

299

private static final String METADATA_LOCATION = "META-INF/reflections/";

300

private static Reflections cachedReflections;

301

302

public static synchronized Reflections getReflections() {

303

if (cachedReflections == null) {

304

// Try to load from pre-saved metadata first (fast)

305

try {

306

cachedReflections = Reflections.collect(METADATA_LOCATION,

307

name -> name.endsWith("-reflections.xml"));

308

309

if (!cachedReflections.getStore().isEmpty()) {

310

return cachedReflections;

311

}

312

} catch (Exception e) {

313

// Fall back to scanning if collection fails

314

}

315

316

// Fall back to runtime scanning (slower)

317

cachedReflections = new Reflections(new ConfigurationBuilder()

318

.forPackages("com.mycompany")

319

.setScanners(Scanners.SubTypes, Scanners.TypesAnnotated));

320

321

// Save for next time

322

try {

323

cachedReflections.save("target/generated-reflections.xml");

324

} catch (Exception e) {

325

// Ignore save errors

326

}

327

}

328

329

return cachedReflections;

330

}

331

}

332

```

333

334

### Serialization in Testing

335

336

```java

337

// Testing with serialized metadata

338

public class SerializationTest {

339

340

@Test

341

public void testMetadataSerialization() throws IOException {

342

// Create test metadata

343

Reflections original = new Reflections("com.mycompany.test");

344

345

// Save to temporary file

346

File tempFile = File.createTempFile("test-reflections", ".xml");

347

original.save(tempFile.getAbsolutePath());

348

349

// Load and compare

350

Reflections loaded = new XmlSerializer().read(new FileInputStream(tempFile));

351

352

// Verify metadata integrity

353

assertEquals(original.getStore().size(), loaded.getStore().size());

354

assertEquals(original.getSubTypesOf(TestInterface.class),

355

loaded.getSubTypesOf(TestInterface.class));

356

357

// Cleanup

358

tempFile.delete();

359

}

360

361

@Test

362

public void testJsonSerialization() throws IOException {

363

Reflections original = new Reflections("com.mycompany.test");

364

365

// Test JSON serialization round-trip

366

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

367

new JsonSerializer().save(original, outputStream.toString());

368

369

ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());

370

Reflections loaded = new JsonSerializer().read(inputStream);

371

372

// Verify equality

373

assertEquals(original.getStore(), loaded.getStore());

374

}

375

}

376

```

377

378

### Error Handling in Serialization

379

380

```java

381

// Robust serialization with error handling

382

public class RobustSerialization {

383

384

public boolean saveWithRetry(Reflections reflections, String filename, int maxRetries) {

385

for (int i = 0; i < maxRetries; i++) {

386

try {

387

reflections.save(filename);

388

return true;

389

} catch (Exception e) {

390

System.err.println("Save attempt " + (i + 1) + " failed: " + e.getMessage());

391

if (i == maxRetries - 1) {

392

e.printStackTrace();

393

}

394

}

395

}

396

return false;

397

}

398

399

public Reflections loadWithFallback(String primaryFile, String fallbackFile) {

400

// Try primary file first

401

try {

402

return new XmlSerializer().read(new FileInputStream(primaryFile));

403

} catch (Exception e) {

404

System.err.println("Failed to load primary metadata: " + e.getMessage());

405

}

406

407

// Try fallback file

408

try {

409

return new XmlSerializer().read(new FileInputStream(fallbackFile));

410

} catch (Exception e) {

411

System.err.println("Failed to load fallback metadata: " + e.getMessage());

412

}

413

414

// Fall back to runtime scanning

415

System.err.println("Falling back to runtime scanning");

416

return new Reflections("com.mycompany");

417

}

418

419

public void validateSerializedMetadata(Reflections reflections) throws IllegalStateException {

420

Store store = reflections.getStore();

421

422

if (store.isEmpty()) {

423

throw new IllegalStateException("Loaded metadata is empty");

424

}

425

426

// Validate expected scanners are present

427

if (!store.containsKey("SubTypes")) {

428

throw new IllegalStateException("SubTypes scanner data missing");

429

}

430

431

if (!store.containsKey("TypesAnnotated")) {

432

throw new IllegalStateException("TypesAnnotated scanner data missing");

433

}

434

435

// Validate data integrity

436

Map<String, Set<String>> subTypes = store.get("SubTypes");

437

if (subTypes.isEmpty()) {

438

System.err.println("Warning: No SubTypes data found");

439

}

440

}

441

}

442

```

443

444

## Serialization Best Practices

445

446

### Format Selection

447

- **XML**: Best for human readability, debugging, and integration with build tools

448

- **JSON**: Best for web applications, RESTful APIs, and lightweight storage

449

- **Java Code**: Best for compile-time type safety and eliminating runtime serialization overhead

450

451

### Performance Considerations

452

- Use serialization for build-time metadata generation to avoid runtime scanning overhead

453

- Cache serialized metadata and check timestamps for invalidation

454

- Use compressed formats for large metadata sets

455

- Consider splitting large metadata into multiple files by package or functionality

456

457

### Build Integration

458

- Generate metadata during build process and include in application artifacts

459

- Use Maven/Gradle plugins to automate metadata generation

460

- Store metadata in classpath locations for automatic discovery

461

- Version metadata files alongside application versions

462

463

### Error Recovery

464

- Always provide fallback to runtime scanning if serialized metadata is corrupted or missing

465

- Validate serialized metadata integrity before use

466

- Use multiple serialization formats for redundancy in critical applications

467

- Implement retry mechanisms for network-based metadata loading

468

469

## Types

470

471

```java { .api }

472

/**

473

* Exception thrown during serialization operations

474

*/

475

class ReflectionsException extends RuntimeException {

476

ReflectionsException(String message);

477

ReflectionsException(String message, Throwable cause);

478

ReflectionsException(Throwable cause);

479

}

480

481

/**

482

* File utility for serialization operations

483

*/

484

interface Serializer {

485

/** Static utility to prepare file with parent directories */

486

static File prepareFile(String filename) {

487

File file = new File(filename);

488

File parent = file.getAbsoluteFile().getParentFile();

489

if (parent != null && !parent.exists()) {

490

parent.mkdirs();

491

}

492

return file;

493

}

494

}

495

```