Let's get started with a Microservice Architecture with Spring Cloud:
Fixing Bean Creation Issues With MapStruct @Mapper Annotations in Spring Applications
Last updated: February 14, 2026
1. Introduction
Bean creation is a core part of how Spring initializes application components. However, when using the @Mapper annotation from MapStruct, we might encounter unexpected bean creation errors during application startup. These issues are typically triggered when Spring doesn’t correctly detect, instantiate, or wire MapStruct-generated mapper implementations. As a result, the application may fail to start, or various runtime exceptions may be raised, indicating that missing or improperly configured mapper beans are present.
In this tutorial, we’ll explore how to effectively resolve issues when creating beans, caused by the @Mapper annotation of MapStruct in Spring applications. Specifically, the focus will be on configuring mappers so that Spring properly detects, instantiates, and wires them, ensuring smooth application startup. Along the way, practical solutions and best practices will demonstrate how to prevent common runtime exceptions, enhance maintainability, and fully leverage the compile-time mapping capabilities of MapStruct.
2. How MapStruct Interacts With Spring Beans
Before we address the issues, it’s essential to understand how MapStruct operates and why Spring sometimes fails to recognize its generated mappers.
2.1. How MapStruct Generates Mappers
MapStruct acts as a compile-time annotation processor that transforms mapping interfaces into concrete implementations.
To illustrate this, consider a simple domain consisting of a Person entity and its corresponding PersonDto class:
public class Person {
private String name;
private int age;
// Constructors, getters, and setters
}
public class PersonDto {
private String name;
private int age;
// Constructors, getters, and setters
}
A mapper interface defines the transformation between these two types:
@Mapper
public interface PersonMapper {
PersonDto toDto(Person person);
}
During compilation, MapStruct creates a class named PersonMapperImpl inside the generated sources directory. This generated class contains the actual field-mapping logic required to convert a Person entity into a PersonDto object. However, despite being available in the generated sources, the implementation remains a plain Java class without any Spring-specific annotations. Consequently, Spring doesn’t include the mapper in its application context and doesn’t manage its lifecycle.
2.2. Why Bean Creation Fails
The Spring dependency injection mechanism expects all required beans to be registered within the application context.
Let’s consider a service that declares a dependency on the mapper:
@Autowired
private PersonMapper personMapper;
When Spring attempts to inject this dependency, it triggers a NoSuchBeanDefinitionException. This happens because MapStruct doesn’t register the generated mapper implementations as Spring beans by default. Since the generated PersonMapperImpl lacks a Spring-specific annotation, the Spring container doesn’t detect it during component scanning.
There are several consequences of this:
- Spring cannot locate the mapper implementation.
- Dependency injection fails.
- Application startup may break with missing-bean errors.
This challenge highlights the need to align the generated MapStruct code with the lifecycle of a Spring bean.
3. Configuring MapStruct Mappers for Spring
To fix the bean creation error discussed in the previous section, MapStruct must be configured to produce mapper implementations that Spring recognizes as managed beans.
3.1. Enabling the Spring Component Model
MapStruct generates Spring–managed mapper beans by specifying componentModel = “spring” in the @Mapper annotation:
@Mapper(componentModel = "spring")
public interface PersonMapper {
PersonDto toDto(Person person);
}
With this configuration, MapStruct generates the implementation that we need:
@Component
public class PersonMapperImpl implements PersonMapper { ... }
In this case, the @Component annotation registers the generated mapper so that Spring treats it as a managed bean. As a result, it becomes part of the application context, making it available for injection into dependent services or controllers. This configuration bridges the MapStruct compile-time implementation with the Spring runtime dependency management, eliminating missing-bean errors and ensuring consistent mapper availability across the application.
3.2. Ensuring Annotation Processing Is Enabled
Even with the correct component model, MapStruct cannot generate mapper implementations without annotation processing. Annotation processors execute during compilation to produce the required classes. Without this configuration, the interfaces compile successfully, but the implementations don’t exist, preventing Spring from registering the beans.
Projects using Maven typically rely on the maven-compiler-plugin to execute the MapStruct annotation processor:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
This configuration ensures that MapStruct generates all mapper implementations during the compile phase.
For Gradle-based projects, annotation processing depends on another setup (depending on the version):
dependencies {
annotationProcessor 'org.mapstruct:mapstruct-processor:${mapstruct.version}'
}
Adding this dependency enables Gradle to execute the MapStruct code generator during compilation, producing mapper implementations that Spring detects and registers as managed beans.
4. Common Bean Creation Issues and Their Solutions
Even after configuring MapStruct and enabling annotation processing, certain bean-creation issues may persist in Spring applications. The following subsections outline the most common causes and their corresponding solutions.
4.1. Package Not Scanned by Spring
Spring Boot automatically scans packages under the package of the main application class. If the mappers are located outside this path, Spring doesn’t detect them, resulting in a NoSuchBeanDefinitionException when trying to inject the mapper.
To fix this, we can ensure that all mapper interfaces are placed within a package scanned by Spring, or explicitly define the packages to scan:
@SpringBootApplication(scanBasePackages = "com.example")
This way, we enable Spring to detect and register MapStruct mappers as beans correctly.
4.2. Conflicts Between Lombok and MapStruct
Projects that combine Lombok and MapStruct often encounter subtle compilation issues, leading to bean creation failures. Since both Lombok and MapStruct rely on annotation processors, any conflict or incorrect processor order may lead to different issues:
- incomplete model classes
- missing getters or setters
- incorrect mapping behavior
Hence, let’s configure the Lombok annotation processor to execute before MapStruct:
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
</path>
</annotationProcessorPaths>
When using Maven, this adjustment should ensure that all model classes are fully generated before MapStruct creates the mapper implementations, eliminating common bean injection issues in Spring applications.
4.3. IDE Annotation Processing Issues
IDE-level annotation processing often prevents MapStruct from generating mapper implementations, even when Maven or Gradle is configured correctly. Many IDEs disable it by default. This situation results in missing *MapperImpl files, bean creation failures, and compilation errors in the IDE.
To resolve such problems, we enable annotation processing in the IDE settings so that MapStruct can automatically generate the required mapper implementations.
5. Conclusion
In this article, we examined how the MapStruct @Mapper annotation interacts with the Spring bean creation process and why mapper implementations sometimes fail to load correctly during application startup. MapStruct generates mapper implementations at compile time, and if Spring doesn’t detect them correctly, a bean error occurs. By configuring the @Mapper annotation with component model and ensuring annotation processing is active in both build tools and IDEs, the generated mappers integrate seamlessly into the Spring application context.
Furthermore, resolving common issues such as mappers placed outside scanned packages, conflicts with Lombok, and annotation processing problems in the IDE stabilizes the mapping layer and avoids runtime bean errors. As a result, proper configuration and build setup, aligned with Spring scanning and injection mechanisms, guarantee the reliable availability of mapper beans.
The source code is available over on GitHub.
















