Map abstract type in Kotlin with MapStruct

Viewed 458

I'm trying to map an abstract class with Mapstruct in Kotlin, but getting the following error:

AnimalMapper.java: error: The return type AnimalOutput is an abstract class or interface. Provide a non abstract / non interface result type or a factory method.

My implementation:

@Mapper(componentModel = "jsr330")
interface AnimalMapper {

    fun mapToDogOutput(dogInput: DogInput): DogOutput

    fun mapToCatOutput(catInput: CatInput): CatOutput

    fun mapToAnimalOutput(animalInput: AnimalInput): AnimalOutput {
        when (animalInput) {
            is DogInput -> mapToDogOutput(animalInput)
            is CatInput -> mapToCatOutput(animalInput)
        }
        throw RuntimeException("Unsupported animal type");
    }
}

sealed class AnimalInput {
    abstract val name: String
}

data class CatInput(
    override val name: String,
    val catProperty: Int,
) : AnimalInput()

data class DogInput(
    override val name: String,
    val dogProperty: Float,
) : AnimalInput()

sealed class AnimalOutput {
    abstract val name: String
}

data class CatOutput(
    override val name: String,
    val catProperty: Int,
) : AnimalOutput()

data class DogOutput(
    override val name: String,
    val dogProperty: Float,
) : AnimalOutput()

In my old java project, this corresponding implementation works as expected:

@Mapper(componentModel = "jsr330")
interface AnimalMapper {

    DogOutput mapToDogOutput(DogInput dogInput);

    CatOutput mapToCatOutput(CatInput catInput);

    default AnimalOutput mapToAnimalOutput(AnimalInput animalInput) {
        if (animalInput instanceof DogInput) {
            return mapToDogOutput((DogInput) animalInput);
        }
        if (animalInput instanceof CatInput) {
            return mapToCatOutput((CatInput) animalInput);
        }
        throw new RuntimeException("Unsupported animal type");
    }
}

public abstract class AnimalInput {
    public String name;
}

public abstract class CatInput extends AnimalInput {
    public String name;
    public int catProperty;
}

public abstract class DogInput extends AnimalInput {
    public String name;
    public float dogProperty;
}

public abstract class AnimalOutput {
    public String name;
}

public abstract class CatOutput extends AnimalOutput {
    public String name;
    public int catProperty;
}

public abstract class DogOutput extends AnimalOutput {
    public String name;
    public float dogProperty;
}

I'm using the following dependency versions:

  • mapstructVersion: 1.4.2.Final
  • kotlinVersion: 1.5.21 (jvmTarget 16)

Anyone have an idea, how to fix this issue in my Kotlin project?

1 Answers

The reason why this is not working in Kotlin is due to the fact that the generated code by Kotlin marks the mapToAnimalOutput method as an abstract method.

You'll need to use @JvmDefault on that method in order for Kotlin to generate the correct modifiers for the method.

Related