Im using dozer in my app for bean to bean mapping...due to its vulnerabilities I want to upgrade to mapstruct
In dozer we had one mapper function for bean to bean mapping and it doing mapping for all different instance.
In MapStruct I m not able to achieve with same one method.
import java.util.Map;
import org.dozer.DozerBeanMapper;
import org.dozer.MappingException;
/**
* Factory for creating DTO objects based on the object identifier that
* is passed to the object creation method.
*/
public class RetrieveChangeSetObjectDtoFactory {
private Map<String, String> objectIdentifiers;
private DozerBeanMapper beanMapper;
public Object createDto(String objectIdentifier, Persistence srcObject) throws MappingException, ClassNotFoundException {
String className = objectIdentifiers.get(objectIdentifier);
if (className == null) {
return null;
}
return beanMapper.map(srcObject, Class.forName(className));
}
/**
* Setter for the object identifiers map, maps the domain objects to their associated DTO classes.
*
* @param objectIdentifiers object identifiers map
*/
public void setObjectIdentifiers(Map<String, String> objectIdentifiers) {
this.objectIdentifiers = objectIdentifiers;
}
/**
* Setter for the bean mapper.
*
* @param beanMapper bean mapper (dozer)
*/
public void setBeanMapper(DozerBeanMapper beanMapper) {
this.beanMapper = beanMapper;
}
}
beanmapper.map
is mapping objects for me...objects getting mapped through hashmap spring bean loading
want to have same one method for mapping all objects stored in hashmap
This is my Spring Dozer bean
One important difference between MapStruct and Dozer is that MapStruct is an annotation processor tool, which means it generates code. You will have to create interfaces / mappings that will generate the mapping code you need.
MapStruct does not have a single entry point that does generic mapping. However, you can implement something like that on your own side if you want to.
You would need a base interface that all your mappers will implement
public interface BaseMapper<S, T> {
T toDto(S source);
S toEntity(T target);
}
You will then need to implement your RetrieveChangeSetObjectDtoFactory
in a slightly different way.
public class RetrieveChangeSetObjectDtoFactory {
private Map<Class<?>, Map<Class<?>, BaseMapper<?, ?>>> entityDtoMappers = new HashMap<>();
public <S, T> Object createDto(Class<S> entityClass, Class<T> dtoClass, S source) {
if (source == null) {
return null;
}
return getMapper(entityClass, dtoClass).toDto(source);
}
public <S, T> Object createSource(Class<S> entityClass, Class<T> dtoClass, T dto) {
if (dto == null) {
return null;
}
return getMapper(entityClass, dtoClass).toEntity(dto);
}
@SuppressWarnings("unchecked")
protected <S, T> BaseMapper<S, T> getMapper(Class<S> entityClass, Class<T> dtoClass) {
// appropriate checks
return (BaseMapper<S, T>) entityDtoMappers.get(entityClass).get(dtoClass);
}
public <S, T> void registerMapper(Class<S> entityClass, Class<T> dtoClass, BaseMapper<S, T> mapper) {
entityDtoMappers.computeIfAbsent(entityClass, key -> new HashMap<>()).put(dtoClass, mapper);
}
}
However, I would recommend to just inject the mappers you need them instead of doing something so generic.