Задать вопрос
  • Mapstruct Mapper выдаёт NullPointerException Cannot invoke because Mapper is null. Как исправить ошибку?

    @duds Автор вопроса
    Сергей Горностаев, в случае с автосгенерированным конструктором ошибка та же, что и при инъекции полем

    "java.lang.NullPointerException: Cannot invoke "com.example.demo.Mappers.TagMapper.tagDTOtoTag(com.example.demo.Models.DTOs.TagDTO)" because "this.tagMapper" is null
    "

    @Mapper(componentModel = MappingConstants.ComponentModel.SPRING,
            injectionStrategy = InjectionStrategy.CONSTRUCTOR,
            uses = {TagMapper.class, DateMapper.class})
    public abstract class ProductMapper {
        
        private DateMapper dateMapper;
        private TagMapper tagMapper;
    
    ...

    java.lang.NullPointerException: Cannot invoke "com.example.demo.Mappers.TagMapper.tagDTOtoTag(com.example.demo.Models.DTOs.TagDTO)" because "this.tagMapper" is null
    at com.example.demo.Mappers.ProductMapper.tagDTOsToTagSet(ProductMapper.java:40) ~[classes/:na]
    at com.example.demo.Mappers.ProductMapperImpl.productDTOtoProduct(ProductMapperImpl.java:37) ~[classes/:na]
    at com.example.demo.Services.Impl.ProductServiceImpl.saveProduct(ProductServiceImpl.java:69) ~[classes/:na]
    at com.example.demo.Controllers.ProductControler.mainCreateProduct(ProductControler.java:26) ~[classes/:na]
    at com.example.demo.Controllers.ProductControler.createProductBodyDTO(ProductControler.java:48) ~[classes/:na]
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:565) ~[na:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.2.0.jar:6.2.0]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986) ~[spring-webmvc-6.2.0.jar:6.2.0]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891) ~[spring-webmvc-6.2.0.jar:6.2.0]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.2.0.jar:6.2.0]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1088) ~[spring-webmvc-6.2.0.jar:6.2.0]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:978) ~[spring-webmvc-6.2.0.jar:6.2.0]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.2.0.jar:6.2.0]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.2.0.jar:6.2.0]
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.33.jar:6.0]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.2.0.jar:6.2.0]
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.33.jar:6.0]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.33.jar:10.1.33]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.0.jar:6.2.0]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.0.jar:6.2.0]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.2.0.jar:6.2.0]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.0.jar:6.2.0]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:397) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:905) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.33.jar:10.1.33]
    at java.base/java.lang.Thread.run(Thread.java:1447) ~[na:na]
  • Mapstruct Mapper выдаёт NullPointerException Cannot invoke because Mapper is null. Как исправить ошибку?

    @duds Автор вопроса
    Dmitry Roo, я конечно рад, за чатгпт, что он смог смаппить строку со строкой, то есть указать разное имя в @Mapping
    Но я же объяснил, что у меня в поле ProductDTO находится массив (TagDTO[] tagDTOs), а в Product находится Set (Set tags), кроме того, в Tag'е поле products - это Set, а в TagDTO вместо этого мне нужен только список названия продуктов, в общем, когда я пытался сделать свой ход, похожим на то, что написал чатгпт (ещё до того, как я задал вопрос), мне выдовало ошибку что-то вроде can't map itarable object to notiterable и can't map property tagDTOs, productNames и т д
    такую логику mapstruct сам не генерирует
  • Mapstruct Mapper выдаёт NullPointerException Cannot invoke because Mapper is null. Как исправить ошибку?

    @duds Автор вопроса
    Сергей Горностаев, Я попробовал использовать абстрактные классы для мапперов
    @Mapper(componentModel = MappingConstants.ComponentModel.SPRING,
            injectionStrategy = InjectionStrategy.CONSTRUCTOR,
            uses = {TagMapper.class, DateMapper.class})
    public abstract class ProductMapper {
    
    
        private final DateMapper dateMapper;
        private final TagMapper tagMapper;
    
        public ProductMapper() {
            this.dateMapper = Mappers.getMapper(DateMapper.class);
            this.tagMapper = Mappers.getMapper(TagMapper.class);;
        }


    Теперь ошибка другая

    Caused by: java.lang.RuntimeException: java.lang.NoSuchMethodException: com.example.demo.Mappers.TagMapperImpl.<init>()
    	at org.mapstruct.factory.Mappers.getMapper(Mappers.java:61) ~[mapstruct-1.6.3.jar:na]
    	at com.example.demo.Mappers.ProductMapper.<init>(ProductMapper.java:28) ~[classes/:na]
    	at com.example.demo.Mappers.ProductMapperImpl.<init>(ProductMapperImpl.java:23) ~[classes/:na]
    	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62) ~[na:na]
    	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) ~[na:na]
    	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:483) ~[na:na]
    	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:209) ~[spring-beans-6.2.0.jar:6.2.0]
    	... 51 common frames omitted
    Caused by: java.lang.NoSuchMethodException: com.example.demo.Mappers.TagMapperImpl.<init>()
    	at java.base/java.lang.Class.getConstructor0(Class.java:3218) ~[na:na]
    	at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2493) ~[na:na]
    	at org.mapstruct.factory.Mappers.doGetMapper(Mappers.java:82) ~[mapstruct-1.6.3.jar:na]
    	at org.mapstruct.factory.Mappers.getMapper(Mappers.java:69) ~[mapstruct-1.6.3.jar:na]
    	at org.mapstruct.factory.Mappers.getMapper(Mappers.java:58) ~[mapstruct-1.6.3.jar:na]
    	... 57 common frames omitted


    at com.example.demo.Mappers.ProductMapper.(ProductMapper.java:28) ~[classes/:na]
    это:
    this.tagMapper = Mappers.getMapper(TagMapper.class);

    а
    at com.example.demo.Mappers.ProductMapperImpl.(ProductMapperImpl.java:23) ~[classes/:na]
    это:
    @Autowired
        public ProductMapperImpl(DateMapper dateMapper) {
    
            this.dateMapper = dateMapper;
        }

    я правильно понимаю, что ошибка в том, что спринг не может найти TagMapper.class в Mappers?
  • Mapstruct Mapper выдаёт NullPointerException Cannot invoke because Mapper is null. Как исправить ошибку?

    @duds Автор вопроса
    Сергей Горностаев, чем должен быть tagMapper?
    полем это ведь не может быть, потому что ProductMapper это интерфейс
  • Mapstruct Mapper выдаёт NullPointerException Cannot invoke because Mapper is null. Как исправить ошибку?

    @duds Автор вопроса
    Сергей Горностаев, в ProductMapper есть аннотация
    @Mapper(componentModel = MappingConstants.ComponentModel.SPRING)

    а в ProductService это просто поле, Spring же сам его инжектит в Service
    @Service
    @Slf4j
    @RequiredArgsConstructor
    public class ProductServiceImpl implements ProductService {
        private final ProductRepository productRepository;
        private final ProductMapper productMapper;
        private final TagServiceImpl tagService;
    /// методы ///
  • Mapstruct Mapper выдаёт NullPointerException Cannot invoke because Mapper is null. Как исправить ошибку?

    @duds Автор вопроса
    public interface ProductMapper {
    
        @Mapping(target = "tags", source = "tagDTOs", qualifiedByName = "tagDTOsToTagSet")
    //    @Mapping(target = "dateOfCreated", source = "stringDate")
        @Mapping(target = "dateOfCreated", source = "stringDate", dateFormat = "yyyy-MM-dd HH:mm", qualifiedByName = "mapStringToLocalDateTime")
        Product productDTOtoProduct(ProductDTO productDTO);
    
        @Mapping(target = "tagDTOs", source = "tags", qualifiedByName = "TagSetToTagDTOs")
    //    @Mapping(target = "stringDate", source = "dateOfCreated")
        @Mapping(target = "stringDate", source = "dateOfCreated", dateFormat = "yyyy-MM-dd HH:mm", qualifiedByName = "mapStringToLocalDateTime")
        ProductDTO productToProductDTO(Product product);
    
        @Named("tagDTOsToTagSet")
        default Set<Tag> tagDTOsToTagSet(TagDTO[] tagDTOs) {
            Set<Tag> tagSet = new HashSet<>();
            for (TagDTO tagDTO : tagDTOs) {
                tagSet.add(TagMapper.INSTANCE.tagDTOtoTag(tagDTO));
            }
            return tagSet;
        }
    
        @Named("TagSetToTagDTOs")
        default TagDTO[] TagSetTotagDTOs(Set<Tag> tagSet) {
            TagDTO[] tagDTOs = new TagDTO[tagSet.size()];
            Iterator<Tag> tagIterator = tagSet.iterator();
            for (int i = 0; i < tagSet.size() ; i ++) {
                tagDTOs[i] = TagMapper.INSTANCE.tagToTagDTO(tagIterator.next());
            }
            return tagDTOs;
        }
    }

    я не стал показывать логику в вопросе, потому что он итак вышел больше 10000 символов, но потом вспомнил, что могу добавить в комментарии
    вот методы в ProductMapper
    если я уберу INSTANCE, как мне вызвать метод TagMapper?
    я правда не смог найти как использовать в Mapper'е методы из другого Mapper'а
  • Mapstruct Mapper выдаёт NullPointerException Cannot invoke because Mapper is null. Как исправить ошибку?

    @duds Автор вопроса
    @Override
        public ProductDTO saveProduct(ProductDTO dto) throws JsonProcessingException {
            if (!StringUtils.isEmpty(dto.getTitle())) {
                List<Product> products = listProducts(dto.getTitle());
                Product product;
                if (!products.isEmpty()) {
                    product = products.getFirst().increaseAmount(products.size());
                    products.removeFirst();
                    productRepository.deleteAll(products);
                    productRepository.save(product);
                    log.info("Updating amount of Products : {}, Amount = {}", product.getTitle(), product.getAmount());
                } else {
                    product = productMapper.productDTOtoProduct(dto);
                    productRepository.save(product);
                    tagService.saveTagSet(product.getTags());
                    log.info("Saving new Product. Title: {}", product.getTitle());
                }
                return productMapper.productToProductDTO(product);
            }
            return null;
        }

    Здесь просто принимается ProductDTO, проверяется, есть ли в базе данных Product с таким же title (listProducts), если нет, то вызывается маппер от DTO, потом сохраняется и возвращается обратно DTO
  • Mapstruct Mapper выдаёт NullPointerException Cannot invoke because Mapper is null. Как исправить ошибку?

    @duds Автор вопроса
    Не уверен, что правильно понял ваш совет, вы имеете ввиду сделать иньекцию не через поле?
    я попробовал изменить TagMapper:
    @Mapper(componentModel = MappingConstants.ComponentModel.SPRING,
            injectionStrategy = InjectionStrategy.CONSTRUCTOR,
            uses = {ProductMapper.class, DateMapper.class})
    public interface TagMapper {
        TagMapper INSTANCE = Mappers.getMapper(TagMapper.class);
    /// Дальше без изменений///
    }

    И теперь Spring вообще не запускается, потому что не может найти INSTANCE, а он мне нужен, потому что я вызываю метод TagMapper'а в ProductMapper'е, чтобы смаппить tags и tagDTOs
    (для этого мне и нужны методы в мапперах, в Product tags это Set, а в ProductDTO tagDTOs, это массив, и mapStruct не сможет смаппить их сам, если оставить только uses = TagMapper.class в ProductMapper, мне пришлось писать свою логику)
    если знаете, можете сказать, как по-другому (без INSTANCE) можно вызвать метод из 1 маппера в другом?
  • Mapstruct Mapper выдаёт NullPointerException Cannot invoke because Mapper is null. Как исправить ошибку?

    @duds Автор вопроса
    Error log:

    2025-06-26T00:02:42.904+07:00 ERROR 23612 --- [demo] [nio-8060-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.NullPointerException: Cannot invoke "com.example.demo.Mappers.DateMapper.mapStringToLocalDateTime(String)" because "this.dateMapper" is null] with root cause
    
    java.lang.NullPointerException: Cannot invoke "com.example.demo.Mappers.DateMapper.mapStringToLocalDateTime(String)" because "this.dateMapper" is null
    	at com.example.demo.Mappers.TagMapperImpl.tagDTOtoTag(TagMapperImpl.java:30) ~[classes/:na]
    	at com.example.demo.Mappers.ProductMapper.tagDTOsToTagSet(ProductMapper.java:39) ~[classes/:na]
    	at com.example.demo.Mappers.ProductMapperImpl.productDTOtoProduct(ProductMapperImpl.java:32) ~[classes/:na]
    	at com.example.demo.Services.Impl.ProductServiceImpl.saveProduct(ProductServiceImpl.java:69) ~[classes/:na]
    	at com.example.demo.Controllers.ProductControler.mainCreateProduct(ProductControler.java:26) ~[classes/:na]
        at com.example.demo.Controllers.ProductControler.createProductBodyDTO(ProductControler.java:48) ~[classes/:na]
        at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.33.jar:6.0]
    	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.2.0.jar:6.2.0]
    	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.33.jar:6.0]


    Я просто не понимаю, почему может возникать NPE, если DateMapperImpl - @component, а и у TagMapperImpl и у ProductMapperImpl есть @autowired DateMapper