Orika Mapper - Невозможно зарегистрировать преобразователи после инициализации MapperFacade.

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

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. Как решить эту проблему? Как зарегистрировать конвертеры перед инициализацией?


person JavaDeveloper    schedule 09.04.2018    source источник


Ответы (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);
}
person Anatoly Shamov    schedule 12.04.2018