or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

code-generation.mdencoding-decoding.mdfile-operations.mdgeneric-data.mdindex.mdmessage-operations.mdreflection-operations.mdschema-evolution.mdschema-system.md

code-generation.mddocs/

0

# Code Generation Support

1

2

Avro's code generation support provides integration with generated Java classes for type-safe, high-performance data operations. Specific operations work with POJOs generated from Avro schemas, offering compile-time type checking and optimized serialization performance.

3

4

## Capabilities

5

6

### Specific Data Utilities

7

8

Core utilities for working with generated Avro classes and their schemas.

9

10

```java { .api }

11

public class SpecificData extends GenericData {

12

public static SpecificData get();

13

14

// Class and schema mapping

15

public static Class<?> getClassName(Schema schema);

16

public Schema getSchema(Class<?> c);

17

public Schema getSchema(Object object);

18

19

// Instance creation

20

public Object newInstance(Class<?> c, Schema schema);

21

public Object createFixed(Object old, Schema schema);

22

public Object createRecord(Object old, Schema schema);

23

public Object createEnum(String symbol, Schema schema);

24

25

// Protocol support

26

public Protocol getProtocol(Class<?> iface);

27

28

// Conversion support

29

public void addLogicalTypeConversion(Conversion<?> conversion);

30

public Conversion<?> getConversionFor(LogicalType logicalType);

31

public Collection<Conversion<?>> getConversions();

32

}

33

```

34

35

**Usage Examples:**

36

37

```java

38

// Get SpecificData instance

39

SpecificData specificData = SpecificData.get();

40

41

// Get class name from schema

42

Schema userSchema = new Schema.Parser().parse(userSchemaJson);

43

Class<?> userClass = SpecificData.getClassName(userSchema);

44

System.out.println("Generated class: " + userClass.getName());

45

46

// Get schema from generated class

47

Schema schemaFromClass = specificData.getSchema(User.class);

48

System.out.println("Schema from class: " + schemaFromClass.getName());

49

50

// Create instance of generated class

51

User user = (User) specificData.newInstance(User.class, userSchema);

52

user.setName("Alice");

53

user.setAge(25);

54

55

// Work with protocols for RPC

56

Protocol userServiceProtocol = specificData.getProtocol(UserService.class);

57

System.out.println("Protocol: " + userServiceProtocol.getName());

58

```

59

60

### Specific Record Interface

61

62

Base interface that all generated record classes implement.

63

64

```java { .api }

65

public interface SpecificRecord extends IndexedRecord {

66

Schema getSchema();

67

68

// Specific record methods are typically generated

69

// For example, for a User schema:

70

// String getName();

71

// void setName(String name);

72

// Integer getAge();

73

// void setAge(Integer age);

74

}

75

```

76

77

**Usage Examples:**

78

79

```java

80

// Using generated record class (example)

81

public class User implements SpecificRecord {

82

private static final Schema SCHEMA$ = new Schema.Parser().parse(SCHEMA_JSON);

83

84

private String name;

85

private Integer age;

86

private String email;

87

88

public User() {}

89

90

public User(String name, Integer age, String email) {

91

this.name = name;

92

this.age = age;

93

this.email = email;

94

}

95

96

@Override

97

public Schema getSchema() {

98

return SCHEMA$;

99

}

100

101

// Generated getters and setters

102

public String getName() { return name; }

103

public void setName(String name) { this.name = name; }

104

105

public Integer getAge() { return age; }

106

public void setAge(Integer age) { this.age = age; }

107

108

public String getEmail() { return email; }

109

public void setEmail(String email) { this.email = email; }

110

111

// IndexedRecord implementation

112

@Override

113

public Object get(int field) {

114

switch (field) {

115

case 0: return name;

116

case 1: return age;

117

case 2: return email;

118

default: throw new IndexOutOfBoundsException();

119

}

120

}

121

122

@Override

123

public void put(int field, Object value) {

124

switch (field) {

125

case 0: name = (String) value; break;

126

case 1: age = (Integer) value; break;

127

case 2: email = (String) value; break;

128

default: throw new IndexOutOfBoundsException();

129

}

130

}

131

}

132

133

// Use generated class

134

User user = new User("Bob", 30, "bob@example.com");

135

Schema userSchema = user.getSchema();

136

System.out.println("User: " + user.getName() + ", Age: " + user.getAge());

137

```

138

139

### Specific Datum Reader

140

141

DatumReader optimized for generated classes with compile-time type safety.

142

143

```java { .api }

144

public class SpecificDatumReader<T> extends GenericDatumReader<T> {

145

public SpecificDatumReader();

146

public SpecificDatumReader(Schema schema);

147

public SpecificDatumReader(Schema writer, Schema reader);

148

public SpecificDatumReader(Class<T> c);

149

public SpecificDatumReader(Class<T> c, Schema writer, Schema reader);

150

151

// Inherited from GenericDatumReader

152

public void setSchema(Schema schema);

153

public void setExpected(Schema reader);

154

public T read(T reuse, Decoder in) throws IOException;

155

}

156

```

157

158

**Usage Examples:**

159

160

```java

161

// Read generated objects from binary data

162

SpecificDatumReader<User> reader = new SpecificDatumReader<>(User.class);

163

164

InputStream inputStream = new FileInputStream("users.avro");

165

BinaryDecoder decoder = DecoderFactory.get().binaryDecoder(inputStream, null);

166

167

// Read specific records with type safety

168

User user1 = reader.read(null, decoder);

169

System.out.println("User name: " + user1.getName());

170

171

// Reuse objects for better performance

172

User reusedUser = null;

173

while (hasMoreData(decoder)) {

174

reusedUser = reader.read(reusedUser, decoder);

175

processUser(reusedUser);

176

}

177

178

// Schema evolution with generated classes

179

Schema writerSchema = getWriterSchema();

180

Schema readerSchema = User.SCHEMA$;

181

SpecificDatumReader<User> evolvingReader =

182

new SpecificDatumReader<>(User.class, writerSchema, readerSchema);

183

184

User evolvedUser = evolvingReader.read(null, decoder);

185

```

186

187

### Specific Datum Writer

188

189

DatumWriter optimized for generated classes with compile-time type safety.

190

191

```java { .api }

192

public class SpecificDatumWriter<T> extends GenericDatumWriter<T> {

193

public SpecificDatumWriter();

194

public SpecificDatumWriter(Schema schema);

195

public SpecificDatumWriter(Class<T> c);

196

197

// Inherited from GenericDatumWriter

198

public void setSchema(Schema schema);

199

public void write(T datum, Encoder out) throws IOException;

200

}

201

```

202

203

**Usage Examples:**

204

205

```java

206

// Write generated objects to binary format

207

SpecificDatumWriter<User> writer = new SpecificDatumWriter<>(User.class);

208

209

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

210

BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(outputStream, null);

211

212

// Write specific records with type safety

213

User user = new User("Charlie", 35, "charlie@example.com");

214

writer.write(user, encoder);

215

encoder.flush();

216

217

// Write multiple users

218

List<User> users = Arrays.asList(

219

new User("Alice", 25, "alice@example.com"),

220

new User("Bob", 30, "bob@example.com"),

221

new User("Carol", 28, "carol@example.com")

222

);

223

224

for (User u : users) {

225

writer.write(u, encoder);

226

}

227

encoder.flush();

228

229

byte[] serializedData = outputStream.toByteArray();

230

```

231

232

### Generated Class Annotations

233

234

Annotations used to mark and configure generated Avro classes.

235

236

```java { .api }

237

@Target(ElementType.TYPE)

238

@Retention(RetentionPolicy.RUNTIME)

239

public @interface AvroGenerated {

240

// Marks classes as Avro-generated

241

}

242

243

@Target(ElementType.TYPE)

244

@Retention(RetentionPolicy.RUNTIME)

245

public @interface FixedSize {

246

int value();

247

}

248

```

249

250

**Usage Examples:**

251

252

```java

253

// Generated record with annotations

254

@AvroGenerated

255

public class User implements SpecificRecord {

256

// Implementation generated by Avro compiler

257

}

258

259

// Generated fixed class with size annotation

260

@AvroGenerated

261

@FixedSize(16)

262

public class MD5Hash implements SpecificFixed {

263

private static final Schema SCHEMA$ = Schema.createFixed("MD5Hash", null, null, 16);

264

private byte[] bytes = new byte[16];

265

266

@Override

267

public Schema getSchema() {

268

return SCHEMA$;

269

}

270

271

@Override

272

public byte[] bytes() {

273

return bytes;

274

}

275

}

276

277

// Check if class is Avro-generated

278

if (User.class.isAnnotationPresent(AvroGenerated.class)) {

279

System.out.println("User class is Avro-generated");

280

}

281

282

// Get fixed size from annotation

283

if (MD5Hash.class.isAnnotationPresent(FixedSize.class)) {

284

FixedSize annotation = MD5Hash.class.getAnnotation(FixedSize.class);

285

System.out.println("Fixed size: " + annotation.value());

286

}

287

```

288

289

### Builder Pattern Support

290

291

Generated classes often include builder patterns for convenient object construction.

292

293

```java { .api }

294

// Example of generated builder (varies by schema)

295

public static class Builder {

296

// Builder methods generated based on schema fields

297

public Builder setName(String name);

298

public Builder setAge(Integer age);

299

public Builder setEmail(String email);

300

301

public User build();

302

public Builder clear();

303

304

// Field checking

305

public boolean hasName();

306

public boolean hasAge();

307

public boolean hasEmail();

308

}

309

```

310

311

**Usage Examples:**

312

313

```java

314

// Using generated builder (example pattern)

315

User user = User.newBuilder()

316

.setName("David")

317

.setAge(40)

318

.setEmail("david@example.com")

319

.build();

320

321

// Build with partial data

322

User partialUser = User.newBuilder()

323

.setName("Eve")

324

.build(); // Age and email will use defaults or be null

325

326

// Check what fields are set

327

User.Builder builder = User.newBuilder();

328

builder.setName("Frank");

329

330

if (builder.hasName()) {

331

System.out.println("Name is set");

332

}

333

if (!builder.hasEmail()) {

334

System.out.println("Email is not set");

335

}

336

337

User finalUser = builder.build();

338

```

339

340

### Specific Error Handling

341

342

Error classes generated from schema error types implement SpecificRecord.

343

344

```java { .api }

345

// Generated error class example

346

@AvroGenerated

347

public class UserNotFoundException extends Exception implements SpecificRecord {

348

private static final Schema SCHEMA$ = parseSchema(ERROR_SCHEMA_JSON);

349

350

private String userId;

351

private String message;

352

353

public UserNotFoundException() {}

354

355

public UserNotFoundException(String userId, String message) {

356

super(message);

357

this.userId = userId;

358

this.message = message;

359

}

360

361

@Override

362

public Schema getSchema() {

363

return SCHEMA$;

364

}

365

366

// Generated getters/setters

367

public String getUserId() { return userId; }

368

public void setUserId(String userId) { this.userId = userId; }

369

370

@Override

371

public String getMessage() { return message; }

372

public void setMessage(String message) { this.message = message; }

373

}

374

```

375

376

**Usage Examples:**

377

378

```java

379

// Throw generated error

380

public User findUser(String userId) throws UserNotFoundException {

381

User user = userRepository.find(userId);

382

if (user == null) {

383

throw new UserNotFoundException(userId, "User not found: " + userId);

384

}

385

return user;

386

}

387

388

// Catch and handle generated error

389

try {

390

User user = findUser("unknown123");

391

} catch (UserNotFoundException e) {

392

System.err.println("Failed to find user: " + e.getUserId());

393

System.err.println("Error message: " + e.getMessage());

394

395

// Error also implements SpecificRecord

396

Schema errorSchema = e.getSchema();

397

System.out.println("Error schema: " + errorSchema.getName());

398

}

399

```

400

401

## Types

402

403

```java { .api }

404

public class SpecificData extends GenericData {

405

// Utilities for generated classes

406

}

407

408

public interface SpecificRecord extends IndexedRecord {

409

Schema getSchema();

410

}

411

412

public interface SpecificFixed extends GenericFixed {

413

// Marker interface for generated fixed classes

414

}

415

416

public class SpecificDatumReader<T> extends GenericDatumReader<T> {

417

// Type-safe reader for generated classes

418

}

419

420

public class SpecificDatumWriter<T> extends GenericDatumWriter<T> {

421

// Type-safe writer for generated classes

422

}

423

424

@Target(ElementType.TYPE)

425

@Retention(RetentionPolicy.RUNTIME)

426

public @interface AvroGenerated {

427

// Annotation for generated classes

428

}

429

430

@Target(ElementType.TYPE)

431

@Retention(RetentionPolicy.RUNTIME)

432

public @interface FixedSize {

433

int value();

434

}

435

436

// Generated class interfaces (examples based on common patterns)

437

public interface Builder<T> {

438

T build();

439

Builder<T> clear();

440

}

441

442

public abstract class SpecificRecordBase implements SpecificRecord {

443

// Base class for generated records (implementation detail)

444

}

445

446

public abstract class SpecificExceptionBase extends Exception implements SpecificRecord {

447

// Base class for generated exceptions

448

}

449

```