Orika Mapper - не удается зарегистрировать преобразователи после инициализации MapperFacade

Я создал класс для копирования свойств bean с помощью API Orika Mapper в приложении spring boot, как показано ниже:

public class ObjectMapper {

    private static MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

    public static ClientEntity toClientEntity(ClientDTO clientDTO) {
        BoundMapperFacade<ClientDTO, ClientEntity> boundMapper = mapperFactory.getMapperFacade(ClientDTO.class, ClientEntity.class);
        return boundMapper.map(clientDTO);
    }   

    public static UserEntity toUserEntity(UserDTO userDTO) {
        mapperFactory.getConverterFactory().registerConverter(new PassThroughConverter(LocalDate.class));
        mapperFactory.getConverterFactory().registerConverter(new PassThroughConverter(LocalTime.class));
        BoundMapperFacade<UserDTO, UserEntity> boundMapper = mapperFactory.getMapperFacade(UserDTO.class, UserEntity.class);
        return boundMapper.map(userDTO);
    }
}

классы UserEntity & UserDTO POJO имеют свойства Java 8 LocalDate и LocalTime, поэтому зарегистрировали преобразователи для mapperFactory. Это отлично работает в первый раз, но при последовательном вызове он выдает следующее исключение:

java.lang.IllegalStateException: Cannot register converters after MapperFacade has been initialized
    at ma.glasnost.orika.converter.DefaultConverterFactory.registerConverter(DefaultConverterFactory.java:192) ~[orika-core-1.4.6.jar:na]
    at ma.glasnost.orika.impl.DefaultMapperFactory$ConverterFactoryFacade.registerConverter(DefaultMapperFactory.java:1614) ~[orika-core-1.4.6.jar:na]

Я понимаю, что это потому, что конвертеры регистрируются после инициализации MapperFacade. Как решить эту проблему? Как зарегистрировать преобразователи перед инициализацией?

1 ответов


в предоставленном фрагменте вы пытаетесь зарегистрировать конвертеры каждый раз toUserEntity() называется. Итак, первый вызов будет работать, но второй потерпит неудачу, потому что MapperFacade будет уже инициализирован во время первого звонка.

вы можете переместить регистрацию преобразователей из метода отображения в статический блок следующим образом:

private static MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
static {
    mapperFactory.getConverterFactory().registerConverter(new PassThroughConverter(LocalDate.class));
    mapperFactory.getConverterFactory().registerConverter(new PassThroughConverter(LocalTime.class));
}

кроме того, вы можете предпочесть двигаться BoundMapperFacadeв статические поля, чтобы избежать ненужных getMapperFacade звонки, как это:

private static BoundMapperFacade<ClientDTO, ClientEntity> clientBoundMapper 
                     = mapperFactory.getMapperFacade(ClientDTO.class, ClientEntity.class);
private static BoundMapperFacade<UserDTO, UserEntity> userBoundMapper 
                     = mapperFactory.getMapperFacade(UserDTO.class, UserEntity.class);

таким образом, методы отображения превратятся в простые однострочные:

public static ClientEntity toClientEntity(ClientDTO clientDTO) {
    return clientBoundMapper.map(clientDTO);
}   

public static UserEntity toUserEntity(UserDTO userDTO) {
    return userBoundMapper.map(userDTO);
}