or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bean-factory.mdbuilder-configuration.mdcore-mapping.mdcustom-conversion.mdevent-system.mdindex.mdmetadata-access.mdprogrammatic-mapping.md

bean-factory.mddocs/

0

# Bean Factory System

1

2

Custom object creation during mapping for advanced instantiation patterns, dependency injection integration, and specialized object construction scenarios.

3

4

## Capabilities

5

6

### Bean Factory Interface

7

8

Primary interface for custom object creation during mapping operations.

9

10

```java { .api }

11

/**

12

* Custom bean factory interface for creating destination objects during mapping

13

*/

14

public interface BeanFactory {

15

/**

16

* Creates a bean instance during mapping

17

* @param source source object being mapped from

18

* @param sourceClass source class type

19

* @param targetBeanId target bean identifier from mapping configuration

20

* @param beanContainer Dozer's bean container for additional context

21

* @return created bean instance

22

*/

23

default Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer);

24

25

/**

26

* Creates a bean instance during mapping (deprecated)

27

* @param source source object being mapped from

28

* @param sourceClass source class type

29

* @param targetBeanId target bean identifier from mapping configuration

30

* @return created bean instance

31

* @deprecated Use createBean(Object, Class, String, BeanContainer) instead

32

*/

33

@Deprecated

34

default Object createBean(Object source, Class<?> sourceClass, String targetBeanId);

35

}

36

```

37

38

### Bean Builder Interface

39

40

Interface for building bean instances with a builder pattern approach.

41

42

```java { .api }

43

/**

44

* Interface for building bean instances

45

*/

46

public interface BeanBuilder {

47

/**

48

* Gets the class type this builder creates

49

* @return class type of beans created by this builder

50

*/

51

Class<?> beanClass();

52

53

/**

54

* Builds and returns a new bean instance

55

* @return constructed bean instance

56

*/

57

Object build();

58

}

59

```

60

61

### Bean Creation Strategy Interface

62

63

Strategy interface for general bean creation patterns.

64

65

```java { .api }

66

/**

67

* Strategy for general bean creation

68

*/

69

public interface BeanGeneralCreationStrategy {

70

/**

71

* Determines if this strategy can create the requested bean

72

* @param directive bean creation directive containing creation requirements

73

* @return true if this strategy can handle the creation, false otherwise

74

*/

75

boolean isApplicable(BeanCreationDirective directive);

76

77

/**

78

* Creates the bean according to the directive

79

* @param directive bean creation directive

80

* @return created bean instance

81

*/

82

Object create(BeanCreationDirective directive);

83

}

84

```

85

86

## Bean Factory Implementation Examples

87

88

### Spring Integration Factory

89

90

```java

91

import org.springframework.context.ApplicationContext;

92

import com.github.dozermapper.core.BeanFactory;

93

94

public class SpringBeanFactory implements BeanFactory {

95

private final ApplicationContext applicationContext;

96

97

public SpringBeanFactory(ApplicationContext applicationContext) {

98

this.applicationContext = applicationContext;

99

}

100

101

@Override

102

public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {

103

if (targetBeanId != null && applicationContext.containsBean(targetBeanId)) {

104

// Create bean by name from Spring context

105

return applicationContext.getBean(targetBeanId);

106

}

107

108

// Fallback to create by type

109

try {

110

Class<?> targetClass = beanContainer.getClassLoader().loadClass(targetBeanId);

111

return applicationContext.getBean(targetClass);

112

} catch (Exception e) {

113

throw new MappingException("Failed to create bean: " + targetBeanId, e);

114

}

115

}

116

}

117

```

118

119

### CDI Integration Factory

120

121

```java

122

import javax.enterprise.context.spi.CreationalContext;

123

import javax.enterprise.inject.spi.Bean;

124

import javax.enterprise.inject.spi.BeanManager;

125

126

public class CDIBeanFactory implements BeanFactory {

127

private final BeanManager beanManager;

128

129

public CDIBeanFactory(BeanManager beanManager) {

130

this.beanManager = beanManager;

131

}

132

133

@Override

134

public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {

135

try {

136

Class<?> targetClass = beanContainer.getClassLoader().loadClass(targetBeanId);

137

Set<Bean<?>> beans = beanManager.getBeans(targetClass);

138

139

if (beans.isEmpty()) {

140

throw new MappingException("No CDI bean found for class: " + targetClass.getName());

141

}

142

143

Bean<?> bean = beanManager.resolve(beans);

144

CreationalContext<?> context = beanManager.createCreationalContext(bean);

145

146

return beanManager.getReference(bean, targetClass, context);

147

} catch (ClassNotFoundException e) {

148

throw new MappingException("Target class not found: " + targetBeanId, e);

149

}

150

}

151

}

152

```

153

154

### Conditional Bean Factory

155

156

```java

157

public class ConditionalBeanFactory implements BeanFactory {

158

private final Map<String, BeanFactory> factoryMap;

159

private final BeanFactory defaultFactory;

160

161

public ConditionalBeanFactory(Map<String, BeanFactory> factoryMap, BeanFactory defaultFactory) {

162

this.factoryMap = factoryMap;

163

this.defaultFactory = defaultFactory;

164

}

165

166

@Override

167

public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {

168

// Choose factory based on source type or other conditions

169

String factoryKey = determineFactoryKey(source, sourceClass, targetBeanId);

170

171

BeanFactory factory = factoryMap.getOrDefault(factoryKey, defaultFactory);

172

return factory.createBean(source, sourceClass, targetBeanId, beanContainer);

173

}

174

175

private String determineFactoryKey(Object source, Class<?> sourceClass, String targetBeanId) {

176

// Business logic to determine which factory to use

177

if (source instanceof DatabaseEntity) {

178

return "database";

179

} else if (source instanceof WebServiceResponse) {

180

return "webservice";

181

} else {

182

return "default";

183

}

184

}

185

}

186

```

187

188

### Builder Pattern Factory

189

190

```java

191

public class BuilderPatternFactory implements BeanFactory {

192

193

@Override

194

public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {

195

try {

196

Class<?> targetClass = beanContainer.getClassLoader().loadClass(targetBeanId);

197

198

// Look for builder pattern

199

Method builderMethod = findBuilderMethod(targetClass);

200

if (builderMethod != null) {

201

Object builder = builderMethod.invoke(null);

202

return callBuildMethod(builder);

203

}

204

205

// Fallback to default constructor

206

return targetClass.getDeclaredConstructor().newInstance();

207

208

} catch (Exception e) {

209

throw new MappingException("Failed to create bean using builder pattern: " + targetBeanId, e);

210

}

211

}

212

213

private Method findBuilderMethod(Class<?> targetClass) {

214

try {

215

// Look for common builder method names

216

return targetClass.getMethod("builder");

217

} catch (NoSuchMethodException e) {

218

try {

219

return targetClass.getMethod("newBuilder");

220

} catch (NoSuchMethodException e2) {

221

return null;

222

}

223

}

224

}

225

226

private Object callBuildMethod(Object builder) throws Exception {

227

Method buildMethod = builder.getClass().getMethod("build");

228

return buildMethod.invoke(builder);

229

}

230

}

231

```

232

233

### Source-Aware Factory

234

235

```java

236

public class SourceAwareFactory implements BeanFactory {

237

238

@Override

239

public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {

240

try {

241

Class<?> targetClass = beanContainer.getClassLoader().loadClass(targetBeanId);

242

243

// Create instance based on source data

244

if (source instanceof User) {

245

return createUserRelatedBean((User) source, targetClass);

246

} else if (source instanceof Order) {

247

return createOrderRelatedBean((Order) source, targetClass);

248

}

249

250

// Default creation

251

return targetClass.getDeclaredConstructor().newInstance();

252

253

} catch (Exception e) {

254

throw new MappingException("Failed to create source-aware bean: " + targetBeanId, e);

255

}

256

}

257

258

private Object createUserRelatedBean(User source, Class<?> targetClass) throws Exception {

259

if (targetClass == UserProfileDto.class) {

260

// Create with user-specific initialization

261

UserProfileDto dto = new UserProfileDto();

262

dto.setCreatedAt(Instant.now());

263

dto.setLastModified(Instant.now());

264

dto.setVersion(1);

265

return dto;

266

}

267

268

return targetClass.getDeclaredConstructor().newInstance();

269

}

270

271

private Object createOrderRelatedBean(Order source, Class<?> targetClass) throws Exception {

272

if (targetClass == OrderSummaryDto.class) {

273

// Create with order-specific initialization

274

OrderSummaryDto dto = new OrderSummaryDto();

275

dto.setOrderDate(source.getCreatedDate());

276

dto.setProcessingStatus("PENDING");

277

return dto;

278

}

279

280

return targetClass.getDeclaredConstructor().newInstance();

281

}

282

}

283

```

284

285

## Bean Factory Registration

286

287

### Single Factory Registration

288

289

```java

290

Mapper mapper = DozerBeanMapperBuilder.create()

291

.withBeanFactory("userFactory", new SpringBeanFactory(applicationContext))

292

.build();

293

```

294

295

### Multiple Factories Registration

296

297

```java

298

Map<String, BeanFactory> factories = new HashMap<>();

299

factories.put("springFactory", new SpringBeanFactory(applicationContext));

300

factories.put("builderFactory", new BuilderPatternFactory());

301

factories.put("conditionalFactory", new ConditionalBeanFactory(factoryMap, defaultFactory));

302

303

Mapper mapper = DozerBeanMapperBuilder.create()

304

.withBeanFactorys(factories)

305

.build();

306

```

307

308

## XML Configuration Integration

309

310

### Mapping File with Bean Factory

311

312

```xml

313

<?xml version="1.0" encoding="UTF-8"?>

314

<mappings xmlns="http://dozermapper.github.io/schema/bean-mapping"

315

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

316

xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping

317

http://dozermapper.github.io/schema/bean-mapping.xsd">

318

319

<mapping>

320

<class-a>com.example.User</class-a>

321

<class-b bean-factory="springFactory">com.example.UserDto</class-b>

322

323

<field>

324

<a>firstName</a>

325

<b>fname</b>

326

</field>

327

</mapping>

328

329

<mapping>

330

<class-a>com.example.Order</class-a>

331

<class-b bean-factory="builderFactory">com.example.OrderDto</class-b>

332

</mapping>

333

334

</mappings>

335

```

336

337

### Programmatic Configuration with Factory

338

339

```java

340

public class FactoryMappingBuilder extends BeanMappingBuilder {

341

@Override

342

public void configure() {

343

mapping(User.class, UserDto.class)

344

.fields("firstName", "fname")

345

.fields("lastName", "lname");

346

347

// Configure destination type to use specific factory

348

mapping(Order.class, type(OrderDto.class).beanFactory("orderFactory"))

349

.fields("orderNumber", "number")

350

.fields("totalAmount", "total");

351

}

352

}

353

```

354

355

## Advanced Bean Factory Patterns

356

357

### Pooled Object Factory

358

359

```java

360

public class PooledObjectFactory implements BeanFactory {

361

private final Map<Class<?>, Queue<Object>> objectPools = new ConcurrentHashMap<>();

362

private final int maxPoolSize;

363

364

public PooledObjectFactory(int maxPoolSize) {

365

this.maxPoolSize = maxPoolSize;

366

}

367

368

@Override

369

public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {

370

try {

371

Class<?> targetClass = beanContainer.getClassLoader().loadClass(targetBeanId);

372

373

// Try to get from pool first

374

Queue<Object> pool = objectPools.get(targetClass);

375

if (pool != null) {

376

Object pooled = pool.poll();

377

if (pooled != null) {

378

resetObject(pooled);

379

return pooled;

380

}

381

}

382

383

// Create new instance if pool is empty

384

return targetClass.getDeclaredConstructor().newInstance();

385

386

} catch (Exception e) {

387

throw new MappingException("Failed to create pooled bean: " + targetBeanId, e);

388

}

389

}

390

391

public void returnToPool(Object obj) {

392

Class<?> clazz = obj.getClass();

393

Queue<Object> pool = objectPools.computeIfAbsent(clazz, k -> new ConcurrentLinkedQueue<>());

394

395

if (pool.size() < maxPoolSize) {

396

pool.offer(obj);

397

}

398

}

399

400

private void resetObject(Object obj) {

401

// Reset object state for reuse

402

// Implementation depends on object structure

403

}

404

}

405

```

406

407

### Prototype-Based Factory

408

409

```java

410

public class PrototypeFactory implements BeanFactory {

411

private final Map<String, Object> prototypes = new ConcurrentHashMap<>();

412

413

public void registerPrototype(String beanId, Object prototype) {

414

prototypes.put(beanId, prototype);

415

}

416

417

@Override

418

public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {

419

Object prototype = prototypes.get(targetBeanId);

420

if (prototype != null) {

421

return clonePrototype(prototype);

422

}

423

424

// Fallback to class-based creation

425

try {

426

Class<?> targetClass = beanContainer.getClassLoader().loadClass(targetBeanId);

427

return targetClass.getDeclaredConstructor().newInstance();

428

} catch (Exception e) {

429

throw new MappingException("Failed to create bean from prototype: " + targetBeanId, e);

430

}

431

}

432

433

private Object clonePrototype(Object prototype) {

434

if (prototype instanceof Cloneable) {

435

try {

436

Method cloneMethod = prototype.getClass().getMethod("clone");

437

cloneMethod.setAccessible(true);

438

return cloneMethod.invoke(prototype);

439

} catch (Exception e) {

440

// Fall back to serialization cloning or other methods

441

}

442

}

443

444

// Implement alternative cloning strategy

445

return deepClone(prototype);

446

}

447

448

private Object deepClone(Object prototype) {

449

// Implement deep cloning (serialization, reflection, etc.)

450

return null; // Placeholder

451

}

452

}

453

```

454

455

## Error Handling

456

457

### Factory Exception Handling

458

459

```java

460

public class RobustBeanFactory implements BeanFactory {

461

private final BeanFactory primaryFactory;

462

private final BeanFactory fallbackFactory;

463

private static final Logger logger = LoggerFactory.getLogger(RobustBeanFactory.class);

464

465

public RobustBeanFactory(BeanFactory primaryFactory, BeanFactory fallbackFactory) {

466

this.primaryFactory = primaryFactory;

467

this.fallbackFactory = fallbackFactory;

468

}

469

470

@Override

471

public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {

472

try {

473

return primaryFactory.createBean(source, sourceClass, targetBeanId, beanContainer);

474

} catch (Exception e) {

475

logger.warn("Primary factory failed for {}, trying fallback", targetBeanId, e);

476

477

try {

478

return fallbackFactory.createBean(source, sourceClass, targetBeanId, beanContainer);

479

} catch (Exception fallbackException) {

480

logger.error("Both primary and fallback factories failed for {}", targetBeanId, fallbackException);

481

throw new MappingException("All factories failed to create bean: " + targetBeanId, fallbackException);

482

}

483

}

484

}

485

}

486

```

487

488

## Best Practices

489

490

### Factory Design

491

- Make factories stateless when possible for thread safety

492

- Use factory method pattern for complex object creation

493

- Implement proper error handling with meaningful exception messages

494

495

### Performance Optimization

496

- Cache expensive factory lookups and configurations

497

- Consider object pooling for frequently created objects

498

- Avoid heavy initialization in factory constructors

499

500

### Integration Patterns

501

- Use dependency injection containers (Spring, CDI) for complex scenarios

502

- Implement factory chains for fallback behavior

503

- Register factories during mapper initialization, not at runtime

504

505

### Testing

506

- Mock bean factories for unit testing mapping behavior

507

- Test factory error scenarios and fallback mechanisms

508

- Verify factory integration with dependency injection frameworks