Andre Vieira
Andre Vieira

Reputation: 80

List<List<String>> mapped to List<String>

I'm learning how to use Mapstruct in a Spring Boot and Kotlin project.

I've got a generated DTO (ThessaurusDTO) that has a List and I need this mapped into a List on my model (Vocab).

It makes sense that MapStruct can't map this automatically, but I know for a fact that the first list will always be size = 1. I have no control on the API the DTO model belongs to. I found on the documentation that I can create define a default method implementation within the interface, which would loosely translate to a normal function in Kotlin

My mapper interface:

@Mapper
interface VocabMapper {

    @Mappings(
            // ...
    )
    fun thessaurusToVocab(thessaurusDTO: ThessaurusDTO): Vocab

    fun metaSyns(nestedList: List<List<String>>): List<String> 
             = nestedList.flatten()
}

When I try to do a build I get the following error:

VocabMapper.java:16: error: Can't map collection element "java.util.List<java.lang.String>" to "java.lang.String ". Consider to declare/implement a mapping method: "java.lang.String map(java.util.List<java.lang.String> value)".

It looks like mapStruct is still trying to automatically do the mapping while ignoring my custom implementation. Am I missing something trivial here?

Upvotes: 0

Views: 456

Answers (2)

Alexey Romanov
Alexey Romanov

Reputation: 170745

I found on the documentation that I can create define a default method implementation within the interface, which would loosely translate to a normal function in Kotlin

From my understand of what I found online, Kotlin does not properly translate an interface function into a default method in Java, but actually generates a class that implements the interface.

If that's the problem, you can annotate metaSyns with @JvmDefault:

Specifies that a JVM default method should be generated for non-abstract Kotlin interface member.

Usages of this annotation require an explicit compilation argument to be specified: either -Xjvm-default=enable or -Xjvm-default=compatibility.

See the link for the difference, but you probably need -Xjvm-default=enable.

Upvotes: 1

Andre Vieira
Andre Vieira

Reputation: 80

I've seen to have fixed this by relying on an abstract based implementation, instead of using an interface. From my understand of what I found online, Kotlin does not properly translate an interface function into a default method in Java, but actually generates a class that implements the interface.

https://github.com/mapstruct/mapstruct/issues/1577

Upvotes: 0

Related Questions