No method found annotated with @Named#value
Asked Answered
T

4

21

I'm having trouble using MapStruct version 1.4.1 when I'm trying to implement my own mapping. This is code that I wrote:

package com.kucazdravlja.user.mappers;

import com.kucazdravlja.user.dto.NoticeBoardDto;
import com.kucazdravlja.user.entities.NoticeBoard;
import com.kucazdravlja.user.entities.NoticeBoardStatus;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;

import java.util.Objects;

@Mapper(uses = {BaseJournalMapper.class})
public interface NoticeBoardMapper {

    @Mapping(source = "status", target = "status", qualifiedByName = "getNoticeBoardStatusName")
    NoticeBoard dtoToEntity(NoticeBoardDto noticeBoardDto);

    @Mapping(source = "status", target = "status", qualifiedByName = "getNoticeBoardStatusDescription")
    NoticeBoardDto entityToDto(NoticeBoard noticeBoard);

    @Named("getNoticeBoardStatusDescription")
    static String getNoticeBoardStatusDescriptionConverter(NoticeBoard noticeBoard) {
        return Objects.requireNonNull(NoticeBoardStatus.findByName(noticeBoard.getStatus())).getDescription();
    }

    @Named("getNoticeBoardStatusName")
    static String getNoticeBoardStatusNameConverter(NoticeBoardDto noticeBoardDto) {
        return Objects.requireNonNull(NoticeBoardStatus.findByName(noticeBoardDto.getStatus())).name();
    }
}

When running application it crashes and gives error

Error:(15, 5) java: Qualifier error. No method found annotated with @Named#value: [ getNoticeBoardStatusName ].

Not sure what is the problem because I have that method with that name.

Thresathresh answered 31/12, 2020 at 6:46 Comment(0)
O
20

In your @Mapping annotation, you are telling mapstruct to use the field "status" as the source for the mapping. But the methods take NoticeBoard and NoticeBoardDto as parameters. You need to change the parameter type to whatever your status is. Assuming it is string:

@Named("getNoticeBoardStatusName")
default String getNoticeBoardStatusNameConverter(String status) {
    return Objects.requireNonNull(NoticeBoardStatus.findByName(status)).name();
}

Also, don't use static methods in mappers, use the default keyword instead.

Obedience answered 31/12, 2020 at 6:50 Comment(0)
G
2

In my case, if you doesn't match the @Context variable type in your method, you will get the same error.

Gloriane answered 17/5, 2023 at 12:11 Comment(0)
P
1

If you need to use the NoticeBoardDto on that named function you can use that also:

    @Mapping(source = ".", target = "status", qualifiedByName = "getNoticeBoardStatusName") // Set source to dot
    NoticeBoard dtoToEntity(NoticeBoardDto noticeBoardDto);


    @Named("getNoticeBoardStatusName")
    static String getNoticeBoardStatusNameConverter(NoticeBoardDto noticeBoardDto) {
        return Objects.requireNonNull(NoticeBoardStatus.findByName(noticeBoardDto.getStatus())).name();
    }
Pardoes answered 7/2, 2024 at 15:9 Comment(0)
N
0

I was trying to map two fields to one object (a relationship object with 2 join columns) and faced this issue. The problem is that I was trying to put @Named annotation and function inside the main mapper class (in AMapper in this case) and not in helper classes (BMappingHelper and CMappingHelper). Here is my working code.

import jakarta.persistence.EntityNotFoundException;
import org.mapstruct.*;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


@Mapper(componentModel = "spring",  uses = {BMappingHelper.class, CMappingHelper.class})
public interface AMapper {
    @Mappings({
            @Mapping(target = "objectLinkedWithTwoFields", source = "dto", qualifiedByName = "mapObjectLinkedWithTwoFields"),
            @Mapping(target = "objectLinkedWithOneFields", source = "dto", qualifiedByName = "mapObjectLinkedWithOneField")
    })
    void updateAEntityFromDTO(ADTO dto, @MappingTarget AEntity entity);

}

@Component
class BMappingHelper {

    @Autowired
    private ObjectLinkedWithTwoFieldsRepository objectLinkedWithTwoFieldsRepository;

    @Named("mapObjectLinkedWithTwoFields")
    public ObjectLinkedWithTwoFields map(ADTO dto) {
        Integer field1 = ADTO.getField1();
        String field2 = ADTO.getField2();
        return objectLinkedWithTwoFieldsRepository.findById(new objectLinkedWithTwoFieldsPK(field1, field2))
                .orElseThrow(() -> new EntityNotFoundException("objectLinkedWithTwoFields not found"));
    }
}

@Component
class CMappingHelper {

    @Autowired
    private ObjectLinkedWithOneFieldRepository objectLinkedWithOneFieldRepository;

    @Named("mapObjectLinkedWithOneField")
    public Standard map(ADTO dto) {
        Integer field1 = dto.getField1();
        return ObjectLinkedWithOneFieldRepository.findById(field1)
                .orElseThrow(() -> new EntityNotFoundException("ObjectLinkedWithOneField not found"));
    }
}
Nineteen answered 22/7, 2024 at 14:53 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.