or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-messages.mdindex.mdio-wire-format.mdjson-text-format.mdreflection-descriptors.mdutilities.md

reflection-descriptors.mddocs/

0

# Reflection and Descriptors

1

2

Comprehensive reflection API for runtime introspection of protocol buffer types, enabling dynamic message handling, tooling, and runtime type discovery without generated classes.

3

4

## Capabilities

5

6

### File Descriptors

7

8

Describes a complete .proto file and its contents, including all message types, enums, services, and extensions defined within it.

9

10

```java { .api }

11

/**

12

* Describes a .proto file and its contents

13

*/

14

public static class Descriptors.FileDescriptor {

15

// Basic information

16

/** Get the file name */

17

public String getName();

18

19

/** Get the proto package name */

20

public String getPackage();

21

22

/** Get file syntax (proto2 or proto3) */

23

public Syntax getSyntax();

24

25

/** Get file options */

26

public DescriptorProtos.FileOptions getOptions();

27

28

// Type discovery

29

/** Get all message types defined in this file */

30

public List<Descriptor> getMessageTypes();

31

32

/** Get all enum types defined in this file */

33

public List<EnumDescriptor> getEnumTypes();

34

35

/** Get all services defined in this file */

36

public List<ServiceDescriptor> getServices();

37

38

/** Get all extensions defined in this file */

39

public List<FieldDescriptor> getExtensions();

40

41

// Dependencies

42

/** Get files this file depends on */

43

public List<FileDescriptor> getDependencies();

44

45

/** Get public dependencies */

46

public List<FileDescriptor> getPublicDependencies();

47

48

// Lookup methods

49

/** Find message type by name within this file */

50

public Descriptor findMessageTypeByName(String name);

51

52

/** Find enum type by name within this file */

53

public EnumDescriptor findEnumTypeByName(String name);

54

55

/** Find service by name within this file */

56

public ServiceDescriptor findServiceByName(String name);

57

58

/** Find extension by name within this file */

59

public FieldDescriptor findExtensionByName(String name);

60

61

// Building file descriptors

62

/** Build from descriptor proto with dependencies */

63

public static FileDescriptor buildFrom(DescriptorProtos.FileDescriptorProto proto,

64

FileDescriptor[] dependencies)

65

throws DescriptorValidationException;

66

67

/** Build from descriptor proto with dependencies and allow unknown dependencies */

68

public static FileDescriptor buildFrom(DescriptorProtos.FileDescriptorProto proto,

69

FileDescriptor[] dependencies,

70

boolean allowUnknownDependencies)

71

throws DescriptorValidationException;

72

73

/** Convert to descriptor proto */

74

public DescriptorProtos.FileDescriptorProto toProto();

75

}

76

```

77

78

### Message Descriptors

79

80

Describes a protocol buffer message type, including all its fields, nested types, and metadata.

81

82

```java { .api }

83

/**

84

* Describes a protocol buffer message type

85

*/

86

public static class Descriptors.Descriptor implements GenericDescriptor {

87

// Basic information

88

/** Get message type name */

89

public String getName();

90

91

/** Get fully qualified message name */

92

public String getFullName();

93

94

/** Get containing file descriptor */

95

public FileDescriptor getFile();

96

97

/** Get containing message type (for nested messages) */

98

public Descriptor getContainingType();

99

100

/** Get message options */

101

public DescriptorProtos.MessageOptions getOptions();

102

103

// Field access

104

/** Get all fields in this message */

105

public List<FieldDescriptor> getFields();

106

107

/** Get all oneof groups in this message */

108

public List<OneofDescriptor> getOneofs();

109

110

/** Get all extensions that can extend this message */

111

public List<FieldDescriptor> getExtensions();

112

113

// Nested type access

114

/** Get all nested message types */

115

public List<Descriptor> getNestedTypes();

116

117

/** Get all nested enum types */

118

public List<EnumDescriptor> getEnumTypes();

119

120

// Capability queries

121

/** Check if this message type is extendable */

122

public boolean isExtendable();

123

124

/** Check if this is a map entry message */

125

public boolean isMapEntry();

126

127

// Field lookup methods

128

/** Find field by name */

129

public FieldDescriptor findFieldByName(String name);

130

131

/** Find field by field number */

132

public FieldDescriptor findFieldByNumber(int number);

133

134

/** Find nested message type by name */

135

public Descriptor findNestedTypeByName(String name);

136

137

/** Find nested enum type by name */

138

public EnumDescriptor findEnumTypeByName(String name);

139

140

// Proto conversion

141

/** Convert to descriptor proto */

142

public DescriptorProtos.DescriptorProto toProto();

143

}

144

```

145

146

### Field Descriptors

147

148

Describes individual fields within protocol buffer messages, including type information, constraints, and metadata.

149

150

```java { .api }

151

/**

152

* Describes a field within a message

153

*/

154

public static class Descriptors.FieldDescriptor implements GenericDescriptor, Comparable<FieldDescriptor> {

155

// Basic information

156

/** Get field name */

157

public String getName();

158

159

/** Get field number */

160

public int getNumber();

161

162

/** Get fully qualified field name */

163

public String getFullName();

164

165

/** Get JSON field name */

166

public String getJsonName();

167

168

/** Get field options */

169

public DescriptorProtos.FieldOptions getOptions();

170

171

// Type information

172

/** Get protocol buffer field type */

173

public Type getType();

174

175

/** Get corresponding Java type */

176

public JavaType getJavaType();

177

178

/** Get wire format type */

179

public WireFormat.FieldType getLiteType();

180

181

// Cardinality and constraints

182

/** Check if field is required (proto2) */

183

public boolean isRequired();

184

185

/** Check if field is optional */

186

public boolean isOptional();

187

188

/** Check if field is repeated */

189

public boolean isRepeated();

190

191

/** Check if repeated field is packed */

192

public boolean isPacked();

193

194

/** Check if field is a map field */

195

public boolean isMapField();

196

197

/** Check if field is an extension field */

198

public boolean isExtension();

199

200

// Default values

201

/** Check if field has explicit default value */

202

public boolean hasDefaultValue();

203

204

/** Get default value for this field */

205

public Object getDefaultValue();

206

207

// Containing types

208

/** Get message type that contains this field */

209

public Descriptor getContainingType();

210

211

/** Get containing oneof group (if part of oneof) */

212

public OneofDescriptor getContainingOneof();

213

214

/** Get extension scope (for extension fields) */

215

public Descriptor getExtensionScope();

216

217

// Referenced types

218

/** Get message type (for message fields) */

219

public Descriptor getMessageType();

220

221

/** Get enum type (for enum fields) */

222

public EnumDescriptor getEnumType();

223

224

// Proto conversion

225

/** Convert to field descriptor proto */

226

public DescriptorProtos.FieldDescriptorProto toProto();

227

228

// Field type enumeration

229

public enum Type {

230

DOUBLE, FLOAT, INT64, UINT64, INT32, FIXED64, FIXED32,

231

BOOL, STRING, GROUP, MESSAGE, BYTES, UINT32, ENUM,

232

SFIXED32, SFIXED64, SINT32, SINT64;

233

234

public JavaType getJavaType();

235

public WireFormat.FieldType getLiteType();

236

}

237

238

public enum JavaType {

239

INT, LONG, FLOAT, DOUBLE, BOOLEAN, STRING, BYTE_STRING, ENUM, MESSAGE;

240

241

public Object getDefaultDefault();

242

}

243

}

244

```

245

246

### Enum Descriptors

247

248

Describes protocol buffer enum types and their values.

249

250

```java { .api }

251

/**

252

* Describes an enum type

253

*/

254

public static class Descriptors.EnumDescriptor implements GenericDescriptor {

255

// Basic information

256

/** Get enum name */

257

public String getName();

258

259

/** Get fully qualified enum name */

260

public String getFullName();

261

262

/** Get containing file */

263

public FileDescriptor getFile();

264

265

/** Get containing message type (for nested enums) */

266

public Descriptor getContainingType();

267

268

/** Get enum options */

269

public DescriptorProtos.EnumOptions getOptions();

270

271

// Value access

272

/** Get all enum values */

273

public List<EnumValueDescriptor> getValues();

274

275

/** Find enum value by name */

276

public EnumValueDescriptor findValueByName(String name);

277

278

/** Find enum value by number */

279

public EnumValueDescriptor findValueByNumber(int number);

280

281

// Proto conversion

282

/** Convert to enum descriptor proto */

283

public DescriptorProtos.EnumDescriptorProto toProto();

284

}

285

286

/**

287

* Describes an enum value

288

*/

289

public static class Descriptors.EnumValueDescriptor implements GenericDescriptor {

290

// Basic information

291

/** Get enum value name */

292

public String getName();

293

294

/** Get enum value number */

295

public int getNumber();

296

297

/** Get fully qualified name */

298

public String getFullName();

299

300

/** Get containing enum type */

301

public EnumDescriptor getType();

302

303

/** Get value options */

304

public DescriptorProtos.EnumValueOptions getOptions();

305

306

/** Convert to enum value descriptor proto */

307

public DescriptorProtos.EnumValueDescriptorProto toProto();

308

}

309

```

310

311

### Service Descriptors

312

313

Describes protocol buffer services and their methods (used with RPC frameworks).

314

315

```java { .api }

316

/**

317

* Describes a service

318

*/

319

public static class Descriptors.ServiceDescriptor implements GenericDescriptor {

320

// Basic information

321

/** Get service name */

322

public String getName();

323

324

/** Get fully qualified service name */

325

public String getFullName();

326

327

/** Get containing file */

328

public FileDescriptor getFile();

329

330

/** Get service options */

331

public DescriptorProtos.ServiceOptions getOptions();

332

333

// Method access

334

/** Get all methods in this service */

335

public List<MethodDescriptor> getMethods();

336

337

/** Find method by name */

338

public MethodDescriptor findMethodByName(String name);

339

340

/** Convert to service descriptor proto */

341

public DescriptorProtos.ServiceDescriptorProto toProto();

342

}

343

344

/**

345

* Describes a service method

346

*/

347

public static class Descriptors.MethodDescriptor implements GenericDescriptor {

348

// Basic information

349

/** Get method name */

350

public String getName();

351

352

/** Get fully qualified method name */

353

public String getFullName();

354

355

/** Get containing service */

356

public ServiceDescriptor getService();

357

358

/** Get method options */

359

public DescriptorProtos.MethodOptions getOptions();

360

361

// Input/output types

362

/** Get input message type */

363

public Descriptor getInputType();

364

365

/** Get output message type */

366

public Descriptor getOutputType();

367

368

// Streaming information

369

/** Check if client streaming */

370

public boolean isClientStreaming();

371

372

/** Check if server streaming */

373

public boolean isServerStreaming();

374

375

/** Convert to method descriptor proto */

376

public DescriptorProtos.MethodDescriptorProto toProto();

377

}

378

```

379

380

### Oneof Descriptors

381

382

Describes oneof field groups within messages.

383

384

```java { .api }

385

/**

386

* Describes a oneof field group

387

*/

388

public static class Descriptors.OneofDescriptor implements GenericDescriptor {

389

// Basic information

390

/** Get oneof name */

391

public String getName();

392

393

/** Get fully qualified oneof name */

394

public String getFullName();

395

396

/** Get containing message type */

397

public Descriptor getContainingType();

398

399

/** Get oneof options */

400

public DescriptorProtos.OneofOptions getOptions();

401

402

// Field access

403

/** Get all fields in this oneof group */

404

public List<FieldDescriptor> getFields();

405

406

/** Get field by index */

407

public FieldDescriptor getField(int index);

408

409

/** Get number of fields in oneof */

410

public int getFieldCount();

411

412

/** Check if oneof is synthetic (proto3 optional) */

413

public boolean isSynthetic();

414

415

/** Convert to oneof descriptor proto */

416

public DescriptorProtos.OneofDescriptorProto toProto();

417

}

418

```

419

420

### Type Registry

421

422

Registry for resolving Any message types by type URL.

423

424

```java { .api }

425

/**

426

* Registry for resolving Any message types

427

*/

428

public class TypeRegistry {

429

// Static factory methods

430

/** Get empty type registry */

431

public static TypeRegistry getEmptyTypeRegistry();

432

433

/** Create new builder */

434

public static Builder newBuilder();

435

436

// Type resolution

437

/** Find type by full name */

438

public Descriptor find(String name);

439

440

/** Find type by type URL */

441

public Descriptor getDescriptorForTypeUrl(String typeUrl);

442

443

/**

444

* Builder for constructing type registries

445

*/

446

public static class Builder {

447

/** Add message type and all its dependencies */

448

public Builder add(Descriptor messageType);

449

450

/** Add multiple message types */

451

public Builder add(Iterable<Descriptor> messageTypes);

452

453

/** Build the type registry */

454

public TypeRegistry build();

455

}

456

}

457

```

458

459

### Descriptor Validation

460

461

Exception handling for descriptor validation errors.

462

463

```java { .api }

464

/**

465

* Exception thrown when descriptor validation fails

466

*/

467

public static class Descriptors.DescriptorValidationException extends Exception {

468

/** Create with description */

469

public DescriptorValidationException(GenericDescriptor problemDescriptor, String description);

470

471

/** Create with description and cause */

472

public DescriptorValidationException(GenericDescriptor problemDescriptor, String description, Throwable cause);

473

474

/** Get descriptor that caused the problem */

475

public GenericDescriptor getProblemDescriptor();

476

477

/** Get problem description */

478

public String getProblemDescription();

479

}

480

481

/**

482

* Base interface for all descriptor types

483

*/

484

public interface GenericDescriptor {

485

/** Get name of this descriptor */

486

String getName();

487

488

/** Get fully qualified name */

489

String getFullName();

490

491

/** Get containing file */

492

FileDescriptor getFile();

493

}

494

```

495

496

**Usage Examples:**

497

498

```java

499

import com.google.protobuf.Descriptors;

500

import com.google.protobuf.TypeRegistry;

501

502

// Working with file descriptors

503

FileDescriptor fileDesc = MyMessage.getDescriptor().getFile();

504

System.out.println("File: " + fileDesc.getName());

505

System.out.println("Package: " + fileDesc.getPackage());

506

507

// Exploring message structure

508

Descriptor messageDesc = MyMessage.getDescriptor();

509

System.out.println("Message: " + messageDesc.getFullName());

510

511

for (FieldDescriptor field : messageDesc.getFields()) {

512

System.out.printf("Field %d: %s (%s)%n",

513

field.getNumber(), field.getName(), field.getType());

514

515

if (field.isRepeated()) {

516

System.out.println(" - Repeated field");

517

}

518

519

if (field.getType() == FieldDescriptor.Type.MESSAGE) {

520

System.out.println(" - Message type: " + field.getMessageType().getFullName());

521

}

522

523

if (field.getContainingOneof() != null) {

524

System.out.println(" - Part of oneof: " + field.getContainingOneof().getName());

525

}

526

}

527

528

// Working with enums

529

for (EnumDescriptor enumDesc : messageDesc.getEnumTypes()) {

530

System.out.println("Enum: " + enumDesc.getName());

531

for (EnumValueDescriptor value : enumDesc.getValues()) {

532

System.out.printf(" %s = %d%n", value.getName(), value.getNumber());

533

}

534

}

535

536

// Building type registry for Any messages

537

TypeRegistry typeRegistry = TypeRegistry.newBuilder()

538

.add(MyMessage.getDescriptor())

539

.add(AnotherMessage.getDescriptor())

540

.build();

541

542

// Find types at runtime

543

Descriptor foundType = typeRegistry.find("com.example.MyMessage");

544

if (foundType != null) {

545

System.out.println("Found type: " + foundType.getFullName());

546

}

547

```

548

549

### Dynamic Message Creation

550

551

Creating and manipulating messages using descriptors without generated classes.

552

553

```java { .api }

554

/**

555

* Dynamic message creation and manipulation using descriptors

556

*/

557

558

// Example: Creating dynamic messages

559

Descriptor messageType = getMessageDescriptor(); // Get from somewhere

560

DynamicMessage.Builder builder = DynamicMessage.newBuilder(messageType);

561

562

// Set fields by descriptor

563

FieldDescriptor nameField = messageType.findFieldByName("name");

564

FieldDescriptor ageField = messageType.findFieldByName("age");

565

566

builder.setField(nameField, "John Doe");

567

builder.setField(ageField, 30);

568

569

DynamicMessage message = builder.build();

570

571

// Read fields by descriptor

572

String name = (String) message.getField(nameField);

573

Integer age = (Integer) message.getField(ageField);

574

575

// Work with repeated fields

576

FieldDescriptor listField = messageType.findFieldByName("items");

577

if (listField.isRepeated()) {

578

builder.addRepeatedField(listField, "item1");

579

builder.addRepeatedField(listField, "item2");

580

581

DynamicMessage messageWithList = builder.build();

582

int count = messageWithList.getRepeatedFieldCount(listField);

583

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

584

String item = (String) messageWithList.getRepeatedField(listField, i);

585

System.out.println("Item " + i + ": " + item);

586

}

587

}

588

```

589

590

## Exception Handling

591

592

Common exceptions when working with descriptors:

593

594

- **DescriptorValidationException**: Thrown when building descriptors from invalid proto definitions

595

- **IllegalArgumentException**: Thrown for invalid field numbers, unknown field names, or type mismatches

596

- **NullPointerException**: Thrown when required parameters are null

597

598

## Types

599

600

```java { .api }

601

// Core descriptor interfaces

602

public interface GenericDescriptor {

603

String getName();

604

String getFullName();

605

FileDescriptor getFile();

606

}

607

608

// Syntax enumeration for proto files

609

public enum Syntax {

610

PROTO2, PROTO3

611

}

612

613

// Descriptor protocol buffer definitions (from descriptor.proto)

614

// These are the underlying proto definitions used to build descriptors

615

public class DescriptorProtos {

616

public static class FileDescriptorProto extends GeneratedMessage { /* ... */ }

617

public static class DescriptorProto extends GeneratedMessage { /* ... */ }

618

public static class FieldDescriptorProto extends GeneratedMessage { /* ... */ }

619

public static class EnumDescriptorProto extends GeneratedMessage { /* ... */ }

620

public static class EnumValueDescriptorProto extends GeneratedMessage { /* ... */ }

621

public static class ServiceDescriptorProto extends GeneratedMessage { /* ... */ }

622

public static class MethodDescriptorProto extends GeneratedMessage { /* ... */ }

623

public static class OneofDescriptorProto extends GeneratedMessage { /* ... */ }

624

625

// Options messages for customizing behavior

626

public static class FileOptions extends GeneratedMessage { /* ... */ }

627

public static class MessageOptions extends GeneratedMessage { /* ... */ }

628

public static class FieldOptions extends GeneratedMessage { /* ... */ }

629

public static class EnumOptions extends GeneratedMessage { /* ... */ }

630

public static class EnumValueOptions extends GeneratedMessage { /* ... */ }

631

public static class ServiceOptions extends GeneratedMessage { /* ... */ }

632

public static class MethodOptions extends GeneratedMessage { /* ... */ }

633

public static class OneofOptions extends GeneratedMessage { /* ... */ }

634

}

635

```