0

I am trying to generate mapstruct implementation class and it is not getting generated. I am using:

  1. Springboot: 2.7.5
  2. Kotlin: 1.7.21
  3. Gradle: 7.5.1
  4. Intellij 2022.2.3 (Ultimate)
  5. Java 17

Following are my implementation classes:

  1. build.gradle.kts

    import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
    
    plugins {
         id("org.springframework.boot") version "2.7.5"
         id("io.spring.dependency-management") version "1.0.11.RELEASE"
    
         val kotlinVersion = "1.7.21"
         kotlin("jvm") version kotlinVersion
         kotlin("plugin.spring") version kotlinVersion
         kotlin("kapt") version kotlinVersion
    }
    
    java.sourceCompatibility = JavaVersion.VERSION_17
    java.targetCompatibility = JavaVersion.VERSION_17
    
    buildscript {
       dependencies {
           classpath("org.jetbrains.kotlin:kotlin-noarg:1.4.21")
           classpath("net.ltgt.gradle:gradle-apt-plugin:0.21")
       }
    }
    
    apply(plugin = "kotlin-jpa")
    apply(plugin = "net.ltgt.apt-idea")
    
    
    dependencies {
          val querydslVersion = "5.0.0"
    
          implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
          api("com.querydsl:querydsl-apt:$querydslVersion")
          kapt("com.querydsl:querydsl-jpa:$querydslVersion") 
    
          val mapstructVersion = "1.5.3.Final"
    
       implementation("org.mapstruct:mapstruct:$mapstructVersion")
          kapt("org.mapstruct:mapstruct-processor:$mapstructVersion")
    }
    
    kapt {
    
     annotationProcessor("org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor")
      //      arguments {
      // Set Mapstruct Configuration options here
      //        arg("mapstruct.defaultComponentModel", "spring")
      //    } 
    }
    
    tasks.withType<KotlinCompile> {
        kotlinOptions {
             freeCompilerArgs = listOf("-Xjsr305=strict")
             jvmTarget = JavaVersion.VERSION_17.toString()
        }
    }
    
    tasks.withType<Test> {
          useJUnitPlatform()
    }
    
  2. DomainModelMapper.kt

    @Mapper(componentModel = MappingConstants.ComponentModel.SPRING, 
            unmappedTargetPolicy = ReportingPolicy.WARN)
    interface DomainModelMapper {
    
         @Mappings(
              Mapping(source = "firstName", target = "first_name"),
              Mapping(source = "lastName", target = "last_name"),
         )
         fun accountCreateToAccount(accountCreate:AccountCreateRequest):Account
     }
    

Exception

nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type 'com.*****.backend.config.DomainModelMapper' 
available: expected at least 1 bean which qualifies as autowire candidate. Dependency 
annotations: {}

I also enabled Annotation Processing in IntelliJ. Below is the screenshot: Intellij annotation processsor

I do not have Lombok in my project. I have tried the official doc, mapstruct spring extension plugin, various SO answers, and blogs.

sd1517
  • 607
  • 4
  • 7
  • 23

1 Answers1

1

Seems to work for me, I've executed the code as follows:

build.gradle.kts

plugins {
    id("org.springframework.boot") version "2.7.5"
    id("io.spring.dependency-management") version "1.0.11.RELEASE"

    val kotlinVersion = "1.6.0"

    kotlin("jvm") version kotlinVersion
    kotlin("plugin.spring") version kotlinVersion
    kotlin("kapt") version kotlinVersion
}
repositories {
    mavenLocal()
    mavenCentral()
}

java.sourceCompatibility = JavaVersion.VERSION_11
java.targetCompatibility = JavaVersion.VERSION_11

buildscript {
    dependencies {
        classpath("org.jetbrains.kotlin:kotlin-noarg:1.4.21")
    }
}

apply(plugin = "kotlin-jpa")

dependencies {
    val mapstructVersion = "1.5.3.Final"

    implementation("org.springframework.boot:spring-boot-starter")


    implementation("org.mapstruct:mapstruct:$mapstructVersion")
    kapt("org.mapstruct:mapstruct-processor:$mapstructVersion")
}

tasks {
    compileKotlin {
        kotlinOptions {
            freeCompilerArgs = listOf("-Xjsr305=strict")
            jvmTarget = JavaVersion.VERSION_11.toString()
        }
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

DomainModelMapper.kt

@Mapper(componentModel = MappingConstants.ComponentModel.SPRING,
    unmappedTargetPolicy = ReportingPolicy.WARN)
interface DomainModelMapper {

    @Mapping(source = "firstName", target = "first_name")
    @Mapping(source = "lastName", target = "last_name")
    fun accountCreateToAccount(accountCreate: AccountCreateRequest): Account
}

And your data classes:

data class Account(
    val first_name: String,
    val last_name: String
)

data class AccountCreateRequest(
    val firstName: String,
    val lastName: String
)

You can see that the output is as follow:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.5)

2022-11-19 16:46:54.420  INFO 45217 --- [           main] com.yonatankarp.AppKt                    : Starting AppKt using Java 11.0.15 on XYZ with PID 45217 (/Users/yonatankarp/IdeaProjects/sandbox/build/classes/kotlin/main started by yonatankarp in /Users/yonatankarp/IdeaProjects/sandbox)
2022-11-19 16:46:54.421  INFO 45217 --- [           main] com.yonatankarp.AppKt                    : No active profile set, falling back to 1 default profile: "default"
2022-11-19 16:46:54.924  INFO 45217 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-11-19 16:46:54.929  INFO 45217 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-11-19 16:46:54.929  INFO 45217 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.68]
2022-11-19 16:46:54.974  INFO 45217 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-11-19 16:46:54.974  INFO 45217 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 520 ms
2022-11-19 16:46:55.117  INFO 45217 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-11-19 16:46:55.123  INFO 45217 --- [           main] com.yonatankarp.AppKt                    : Started AppKt in 0.859 seconds (JVM running for 1.032)

Please note that according to this answer net.ltgt.apt-idea is no longer needed after Gradle 7.2 and actually failed my build...

Yonatan Karp-Rudin
  • 1,056
  • 8
  • 24
  • which version of kotlin? – sd1517 Nov 19 '22 at 17:52
  • As you can see in the `build.gradle.kts` above I'm using the same version -`1.6.0` :) – Yonatan Karp-Rudin Nov 19 '22 at 17:56
  • the only changes I did was removing the plugins and adding the `repositories` section - I added the data classes for you to ensure that they're looking the same as you'd expect them to look like – Yonatan Karp-Rudin Nov 19 '22 at 17:57
  • Hi, my bad, I overlooked it. Thank you. I tried with your configs and unfortunately, the issue still persists. I have then updated kotlin to 1.7.21 and my intellij to 2022.2.3. To add I also have mongo annotation processor. That seems to work. I am updating the post now. Please have a look. – sd1517 Nov 20 '22 at 11:42
  • Could you maybe create a minimal github repo that reproduces the issue that I can clone and run locally? I think that it would become easier to understand the root cause – Yonatan Karp-Rudin Nov 20 '22 at 11:47
  • Good idea, I think that the mapper functions are wrong in terms of source and destination classes. I will check it out, if that does not work, I will create a minimal repo. Thanks for your help and prompt response. :) – sd1517 Nov 20 '22 at 11:49
  • Sure thing, let me know at the end so I can update my answer accordingly as the response for this question :) – Yonatan Karp-Rudin Nov 20 '22 at 11:50
  • My apologies for responding late. I have now created a minimal application, but the issue seems to still persist. Following is the repo link: https://github.com/shibasish/mapstruct-springbooot-demo – sd1517 Nov 25 '22 at 16:19
  • 1
    Have you tried this one BTW? https://3lexw.medium.com/how-to-use-mapstruct-in-kotlin-spring-with-injection-spring-services-and-repositories-5c3f468ee261 – Yonatan Karp-Rudin Nov 25 '22 at 17:15