Java Bean to Java Bean mapper that recursively copies data from one object to another
—
Custom object creation during mapping for advanced instantiation patterns, dependency injection integration, and specialized object construction scenarios.
Primary interface for custom object creation during mapping operations.
/**
* Custom bean factory interface for creating destination objects during mapping
*/
public interface BeanFactory {
/**
* Creates a bean instance during mapping
* @param source source object being mapped from
* @param sourceClass source class type
* @param targetBeanId target bean identifier from mapping configuration
* @param beanContainer Dozer's bean container for additional context
* @return created bean instance
*/
default Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer);
/**
* Creates a bean instance during mapping (deprecated)
* @param source source object being mapped from
* @param sourceClass source class type
* @param targetBeanId target bean identifier from mapping configuration
* @return created bean instance
* @deprecated Use createBean(Object, Class, String, BeanContainer) instead
*/
@Deprecated
default Object createBean(Object source, Class<?> sourceClass, String targetBeanId);
}Interface for building bean instances with a builder pattern approach.
/**
* Interface for building bean instances
*/
public interface BeanBuilder {
/**
* Gets the class type this builder creates
* @return class type of beans created by this builder
*/
Class<?> beanClass();
/**
* Builds and returns a new bean instance
* @return constructed bean instance
*/
Object build();
}Strategy interface for general bean creation patterns.
/**
* Strategy for general bean creation
*/
public interface BeanGeneralCreationStrategy {
/**
* Determines if this strategy can create the requested bean
* @param directive bean creation directive containing creation requirements
* @return true if this strategy can handle the creation, false otherwise
*/
boolean isApplicable(BeanCreationDirective directive);
/**
* Creates the bean according to the directive
* @param directive bean creation directive
* @return created bean instance
*/
Object create(BeanCreationDirective directive);
}import org.springframework.context.ApplicationContext;
import com.github.dozermapper.core.BeanFactory;
public class SpringBeanFactory implements BeanFactory {
private final ApplicationContext applicationContext;
public SpringBeanFactory(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {
if (targetBeanId != null && applicationContext.containsBean(targetBeanId)) {
// Create bean by name from Spring context
return applicationContext.getBean(targetBeanId);
}
// Fallback to create by type
try {
Class<?> targetClass = beanContainer.getClassLoader().loadClass(targetBeanId);
return applicationContext.getBean(targetClass);
} catch (Exception e) {
throw new MappingException("Failed to create bean: " + targetBeanId, e);
}
}
}import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
public class CDIBeanFactory implements BeanFactory {
private final BeanManager beanManager;
public CDIBeanFactory(BeanManager beanManager) {
this.beanManager = beanManager;
}
@Override
public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {
try {
Class<?> targetClass = beanContainer.getClassLoader().loadClass(targetBeanId);
Set<Bean<?>> beans = beanManager.getBeans(targetClass);
if (beans.isEmpty()) {
throw new MappingException("No CDI bean found for class: " + targetClass.getName());
}
Bean<?> bean = beanManager.resolve(beans);
CreationalContext<?> context = beanManager.createCreationalContext(bean);
return beanManager.getReference(bean, targetClass, context);
} catch (ClassNotFoundException e) {
throw new MappingException("Target class not found: " + targetBeanId, e);
}
}
}public class ConditionalBeanFactory implements BeanFactory {
private final Map<String, BeanFactory> factoryMap;
private final BeanFactory defaultFactory;
public ConditionalBeanFactory(Map<String, BeanFactory> factoryMap, BeanFactory defaultFactory) {
this.factoryMap = factoryMap;
this.defaultFactory = defaultFactory;
}
@Override
public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {
// Choose factory based on source type or other conditions
String factoryKey = determineFactoryKey(source, sourceClass, targetBeanId);
BeanFactory factory = factoryMap.getOrDefault(factoryKey, defaultFactory);
return factory.createBean(source, sourceClass, targetBeanId, beanContainer);
}
private String determineFactoryKey(Object source, Class<?> sourceClass, String targetBeanId) {
// Business logic to determine which factory to use
if (source instanceof DatabaseEntity) {
return "database";
} else if (source instanceof WebServiceResponse) {
return "webservice";
} else {
return "default";
}
}
}public class BuilderPatternFactory implements BeanFactory {
@Override
public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {
try {
Class<?> targetClass = beanContainer.getClassLoader().loadClass(targetBeanId);
// Look for builder pattern
Method builderMethod = findBuilderMethod(targetClass);
if (builderMethod != null) {
Object builder = builderMethod.invoke(null);
return callBuildMethod(builder);
}
// Fallback to default constructor
return targetClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new MappingException("Failed to create bean using builder pattern: " + targetBeanId, e);
}
}
private Method findBuilderMethod(Class<?> targetClass) {
try {
// Look for common builder method names
return targetClass.getMethod("builder");
} catch (NoSuchMethodException e) {
try {
return targetClass.getMethod("newBuilder");
} catch (NoSuchMethodException e2) {
return null;
}
}
}
private Object callBuildMethod(Object builder) throws Exception {
Method buildMethod = builder.getClass().getMethod("build");
return buildMethod.invoke(builder);
}
}public class SourceAwareFactory implements BeanFactory {
@Override
public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {
try {
Class<?> targetClass = beanContainer.getClassLoader().loadClass(targetBeanId);
// Create instance based on source data
if (source instanceof User) {
return createUserRelatedBean((User) source, targetClass);
} else if (source instanceof Order) {
return createOrderRelatedBean((Order) source, targetClass);
}
// Default creation
return targetClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new MappingException("Failed to create source-aware bean: " + targetBeanId, e);
}
}
private Object createUserRelatedBean(User source, Class<?> targetClass) throws Exception {
if (targetClass == UserProfileDto.class) {
// Create with user-specific initialization
UserProfileDto dto = new UserProfileDto();
dto.setCreatedAt(Instant.now());
dto.setLastModified(Instant.now());
dto.setVersion(1);
return dto;
}
return targetClass.getDeclaredConstructor().newInstance();
}
private Object createOrderRelatedBean(Order source, Class<?> targetClass) throws Exception {
if (targetClass == OrderSummaryDto.class) {
// Create with order-specific initialization
OrderSummaryDto dto = new OrderSummaryDto();
dto.setOrderDate(source.getCreatedDate());
dto.setProcessingStatus("PENDING");
return dto;
}
return targetClass.getDeclaredConstructor().newInstance();
}
}Mapper mapper = DozerBeanMapperBuilder.create()
.withBeanFactory("userFactory", new SpringBeanFactory(applicationContext))
.build();Map<String, BeanFactory> factories = new HashMap<>();
factories.put("springFactory", new SpringBeanFactory(applicationContext));
factories.put("builderFactory", new BuilderPatternFactory());
factories.put("conditionalFactory", new ConditionalBeanFactory(factoryMap, defaultFactory));
Mapper mapper = DozerBeanMapperBuilder.create()
.withBeanFactorys(factories)
.build();<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozermapper.github.io/schema/bean-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping
http://dozermapper.github.io/schema/bean-mapping.xsd">
<mapping>
<class-a>com.example.User</class-a>
<class-b bean-factory="springFactory">com.example.UserDto</class-b>
<field>
<a>firstName</a>
<b>fname</b>
</field>
</mapping>
<mapping>
<class-a>com.example.Order</class-a>
<class-b bean-factory="builderFactory">com.example.OrderDto</class-b>
</mapping>
</mappings>public class FactoryMappingBuilder extends BeanMappingBuilder {
@Override
public void configure() {
mapping(User.class, UserDto.class)
.fields("firstName", "fname")
.fields("lastName", "lname");
// Configure destination type to use specific factory
mapping(Order.class, type(OrderDto.class).beanFactory("orderFactory"))
.fields("orderNumber", "number")
.fields("totalAmount", "total");
}
}public class PooledObjectFactory implements BeanFactory {
private final Map<Class<?>, Queue<Object>> objectPools = new ConcurrentHashMap<>();
private final int maxPoolSize;
public PooledObjectFactory(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}
@Override
public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {
try {
Class<?> targetClass = beanContainer.getClassLoader().loadClass(targetBeanId);
// Try to get from pool first
Queue<Object> pool = objectPools.get(targetClass);
if (pool != null) {
Object pooled = pool.poll();
if (pooled != null) {
resetObject(pooled);
return pooled;
}
}
// Create new instance if pool is empty
return targetClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new MappingException("Failed to create pooled bean: " + targetBeanId, e);
}
}
public void returnToPool(Object obj) {
Class<?> clazz = obj.getClass();
Queue<Object> pool = objectPools.computeIfAbsent(clazz, k -> new ConcurrentLinkedQueue<>());
if (pool.size() < maxPoolSize) {
pool.offer(obj);
}
}
private void resetObject(Object obj) {
// Reset object state for reuse
// Implementation depends on object structure
}
}public class PrototypeFactory implements BeanFactory {
private final Map<String, Object> prototypes = new ConcurrentHashMap<>();
public void registerPrototype(String beanId, Object prototype) {
prototypes.put(beanId, prototype);
}
@Override
public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {
Object prototype = prototypes.get(targetBeanId);
if (prototype != null) {
return clonePrototype(prototype);
}
// Fallback to class-based creation
try {
Class<?> targetClass = beanContainer.getClassLoader().loadClass(targetBeanId);
return targetClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new MappingException("Failed to create bean from prototype: " + targetBeanId, e);
}
}
private Object clonePrototype(Object prototype) {
if (prototype instanceof Cloneable) {
try {
Method cloneMethod = prototype.getClass().getMethod("clone");
cloneMethod.setAccessible(true);
return cloneMethod.invoke(prototype);
} catch (Exception e) {
// Fall back to serialization cloning or other methods
}
}
// Implement alternative cloning strategy
return deepClone(prototype);
}
private Object deepClone(Object prototype) {
// Implement deep cloning (serialization, reflection, etc.)
return null; // Placeholder
}
}public class RobustBeanFactory implements BeanFactory {
private final BeanFactory primaryFactory;
private final BeanFactory fallbackFactory;
private static final Logger logger = LoggerFactory.getLogger(RobustBeanFactory.class);
public RobustBeanFactory(BeanFactory primaryFactory, BeanFactory fallbackFactory) {
this.primaryFactory = primaryFactory;
this.fallbackFactory = fallbackFactory;
}
@Override
public Object createBean(Object source, Class<?> sourceClass, String targetBeanId, BeanContainer beanContainer) {
try {
return primaryFactory.createBean(source, sourceClass, targetBeanId, beanContainer);
} catch (Exception e) {
logger.warn("Primary factory failed for {}, trying fallback", targetBeanId, e);
try {
return fallbackFactory.createBean(source, sourceClass, targetBeanId, beanContainer);
} catch (Exception fallbackException) {
logger.error("Both primary and fallback factories failed for {}", targetBeanId, fallbackException);
throw new MappingException("All factories failed to create bean: " + targetBeanId, fallbackException);
}
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-com-github-dozermapper--dozer-core