29 October 2026

MapStruct: An Overview

 (viejo confiable).

Introduction

MapStruct is a code generator that greatly simplifies the implementation of mappings between Java bean types, following a convention-over-configuration approach.

It uses annotations to generate mapping code at compile time, ensuring high performance and reducing boilerplate code.

There are several Java DTO mapping libraries, such as MapStruct, Dozer, and ModelMapper. MapStruct stands out by generating mapping implementations during compilation rather than relying on runtime reflection.

The core solution involves creating an interface annotated with @Mapper. During compilation, the MapStruct annotation processor generates the mapping implementation. With Maven, this can be done by running mvn clean install.

This approach reduces repetitive code and makes object mapping easier to maintain.

Basic Usage of MapStruct

To use MapStruct, you need to define a mapper interface and annotate it with @Mapper.

Here is a simple example:

@Mapper
public interface SimpleSourceDestinationMapper {

    SimpleSourceDestinationMapper INSTANCE =
        Mappers.getMapper(SimpleSourceDestinationMapper.class);

    SimpleDestination sourceToDestination(SimpleSource source);

    SimpleSource destinationToSource(SimpleDestination destination);
}

The interface defines two mapping methods: one converts a SimpleSource object into a SimpleDestination object, while the other performs the reverse mapping.

The Mappers.getMapper() method provides an instance of the generated implementation. MapStruct generates the implementation automatically during compilation.

Nested Object Mapping

MapStruct can also map objects containing nested objects. The @Mapping annotation allows you to specify the source and target properties explicitly.

Consider an employee entity containing an identifier, a name, and a division. The corresponding DTO may use different property names and contain a nested division DTO.

@Mapper
public interface EmployeeMapper {

    @Mapping(target = "employeeId", source = "entity.id")
    @Mapping(target = "employeeName", source = "entity.name")
    EmployeeDTO employeeToEmployeeDTO(Employee entity);

    @Mapping(target = "id", source = "dto.employeeId")
    @Mapping(target = "name", source = "dto.employeeName")
    Employee employeeDTOToEmployee(EmployeeDTO dto);

    DivisionDTO divisionToDivisionDTO(Division entity);

    Division divisionDTOToDivision(DivisionDTO dto);
}

In this example, the source and target property names are different. The @Mapping annotations explicitly define how these properties correspond to each other.

The mapper also declares methods for converting Division objects into DivisionDTO objects and vice versa.

MapStruct can reuse mapping methods to handle nested objects, allowing complex object structures to be mapped through a combination of simple mappings.

List POJO Mapping

Mapping collections sometimes requires additional logic, particularly when the destination contains a list of objects that must be constructed from a source object.

In the following example, a mapper uses an expression to call a custom default method that creates a list of inner objects.

@Mapper
public interface ListPojoMapper {

    @Mapping(
        target = "innerPojoList",
        expression = "java(mapInnerPojoList(firstPojo))"
    )
    SecondPojo mapFirstPojoToSecondPojo(FirstPojo firstPojo);

    default List<InnerPojo> mapInnerPojoList(FirstPojo firstPojo) {

        System.out.println(
            "mapInnerPojoList..... default interface method!"
        );

        List<InnerPojo> innerPojos =
            java.util.Arrays.asList(new InnerPojo());

        for (InnerPojo innerPojo : innerPojos) {
            innerPojo.setInnerString(
                firstPojo.getStringAttribute()
            );
        }

        List<InnerPojo> result =
            new ArrayList<InnerPojo>(innerPojos);

        return result;
    }
}

The mapInnerPojoList() method demonstrates how a custom mapping method can be implemented directly in a mapper interface using the default keyword.

The method creates an InnerPojo object, assigns a string attribute from the source object, and returns a list containing the resulting object.

The expression attribute in @Mapping allows MapStruct to invoke this custom method when generating the mapping implementation.

This technique is useful when a mapping cannot be expressed as a straightforward property-to-property assignment.

Composite Inner POJOs

MapStruct can handle complex mappings, including composite POJOs containing inner POJOs.

Consider an EmployeeDTO class with the following properties:

@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class EmployeeDTO {

    private int employeeId;
    private String employeeName;
    private DivisionDTO division;
}

The nested DivisionDTO class contains its own properties:

@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DivisionDTO {

    private int id;
    private String name;
}

The mapper can define the conversion methods for both the employee and division objects:

@Mapper
public interface EmployeeMapper {

    @Mapping(target = "employeeId", source = "entity.id")
    @Mapping(target = "employeeName", source = "entity.name")
    EmployeeDTO employeeToEmployeeDTO(Employee entity);

    @Mapping(target = "id", source = "dto.employeeId")
    @Mapping(target = "name", source = "dto.employeeName")
    Employee employeeDTOToEmployee(EmployeeDTO dto);

    DivisionDTO divisionToDivisionDTO(Division entity);

    Division divisionDTOToDivision(DivisionDTO dto);
}

This example illustrates how MapStruct can map properties with different names and work with nested object structures.

By defining the appropriate mapping methods, developers can separate the mapping logic from the business logic and avoid manually copying properties between objects.

Generated Code

One of the main advantages of MapStruct is that it generates ordinary Java code during compilation.

For example, the generated implementation of SimpleSourceDestinationMapper can look like this:

import javax.annotation.processing.Generated;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2025-02-18T15:58:04-0300",
    comments = "version: 1.6.3, compiler: javac"
)
public class SimpleSourceDestinationMapperImpl
        implements SimpleSourceDestinationMapper {

    @Override
    public SimpleDestination sourceToDestination(
            SimpleSource source) {

        if (source == null) {
            return null;
        }

        SimpleDestination.SimpleDestinationBuilder
            simpleDestination = SimpleDestination.builder();

        simpleDestination.name(source.getName());
        simpleDestination.description(source.getDescription());

        return simpleDestination.build();
    }

    @Override
    public SimpleSource destinationToSource(
            SimpleDestination destination) {

        if (destination == null) {
            return null;
        }

        SimpleSource.SimpleSourceBuilder simpleSource =
            SimpleSource.builder();

        simpleSource.name(destination.getName());
        simpleSource.description(destination.getDescription());

        return simpleSource.build();
    }
}

The generated implementation checks for null values, creates the destination object using its builder, copies the properties, and returns the resulting instance.

Notice that the generated code contains direct method calls such as getName() and getDescription(). This is one of the reasons MapStruct can provide high-performance mappings without relying on runtime reflection for these operations.

The generated classes are produced by the annotation processor during compilation. Developers normally work with the mapper interface rather than manually maintaining the generated implementation.

Drawbacks and Limitations

MapStruct works well when mapping large numbers of objects with similar structures and many attributes. It can significantly reduce repetitive code when converting between entities, DTOs, and other Java bean types.

However, mapping becomes more complex when the source and destination objects have significantly different structures.

Nested classes and composite objects may require additional mapping methods or explicit configuration to determine how properties should be transferred between outer and inner objects.

Mapping can involve Java beans, primitive values, nested classes, and collections. Collections may require particular attention when the destination structure differs from the source structure or when each element needs custom transformation logic.

For these situations, custom methods and explicit @Mapping annotations can help make the intended conversion clear.

Conclusion

MapStruct is a useful tool for Java applications that need to convert objects between different representations. By generating mapping implementations at compile time, it reduces boilerplate code while maintaining readable and efficient Java implementations.

Its annotation-based approach supports straightforward property mapping, nested objects, collections, and custom conversion logic. For complex object structures, developers may need to define explicit mappings and custom methods.

Overall, MapStruct is a practical option for simplifying DTO mapping and keeping conversion logic separate from the rest of the application.

References

23 October 2026

22 October 2026

Cuantización / Quantization

La cuantización en inteligencia artificial es un proceso que reduce el número de bits utilizados para representar los pesos y activaciones de un modelo, pasando de formatos de alta precisión (como FP32 o FP16) a formatos de menor precisión (como INT8, INT4 o inferiores).

 

21 October 2026

Feature creep

Feature creep is the excessive ongoing expansion or addition of new features in a product,[1] especially in computer software, video games (where it should not be confused with power creep) and consumer and business electronics. These extra features go beyond the basic function of the product and can result in software bloat and over-complication, rather than simple design.

--wikipedia

 

14 October 2026

Orthogonal Array Testing

Un Orthogonal Array (OA) es una matriz experimental utilizada para estudiar como diferentes factores afectan un resultado, reduciendo la cantidad de experimentos necesarios.

El metodo Taguchi utiliza estas matrices para diseñar experimentos de manera eficiente, especialmente en ingenieria, optimizacion de procesos y control de calidad.

En Desarrollo de Software es una buena tecnica para ser usado en QA (Quality Assurance), 

---------------------------------------

Taguchi Orthogonal Array L4

Three factors with two levels require 8 experiments in a full factorial design, but only 4 with L4.

Experiment A: Threads B: Batch C: Pool
1101005
210100020
310010020
410010005

Key idea: Each pair of columns contains all four combinations of levels exactly once.

----------------------------------


Group Testing / Combinatorial Group Testing.

  • Orthogonal Array Testing (OAT) — usa matrices ortogonales para reducir sistematicamente las combinaciones.
  • Pairwise Testing — garantiza que cada par de valores de parametros aparezca al menos una vez.
  • Combinatorial Testing — nombre general para estas tecnicas.
  • Covering Array Testing — busca un conjunto reducido de casos que cubra todas las combinaciones de t parametros.
  • Equivalence Partitioning — divide entradas en clases y prueba representantes, aunque es otra tecnica.
  • Boundary Value Analysis — prueba valores en los limites.
  • Combinatorial Interaction Testing (CIT) — enfocado en detectar fallos producidos por interacciones entre parametros.
  • Design of Experiments (DOE) — viene de estadistica/experimentacion y tambien busca obtener mucha informacion con menos experimentos.


*AI-assisted content

09 October 2026

Jax London 26

 


Wed 07.10.2026

  1. Welcome and Opening Keynote of JAX London 2026
    Sebastian Meyen

  2. Worth a Million Arguments
    Venkat Subramaniam (prototype!)

  3. Low Latency Machine - Can Generative AI Write High-Performance Code?
    Mark Price

  4. Four Green Ticks – Yet Still Hacked: Threat Modelling for AI Agents
    Christian Schneider

  5. Security in the Age of AI – Ask the Expert
    Charles Weir

  6. Small Signals, Big Incidents: Catching Production Problems in the Performance Lab with JFR & AI
    Ram Lakshmanan

  7. Building Agentic AI with Small Language Models — Locally and Efficiently
    John Davies| Incept5

  8. Build Your Own Private AI Cluster for the Office
    John Davies| Incept5



Thr 08.10.2026

  1. AI and the Future of Enterprise Software
    Rod Johnson| Embabel

  2. Create Your Own Role-Playing Game with Agentic AI Using Spring AI
    Arnaud Jean| AWS

  3. Architecture Observability in Agentic Engineering
    Victor Rentea| Independent Trainer

  4. AI Literacy for Developers: Thinking Clearly While AI Writes the Code
    Russell Miles| TechTalk

  5. Trade-Offs Are Everything: Non-functional Requirements For the AI Era
    Eoin Woods| Artechra

  6. A2UI & MCP-UI: Agent-Driven Interfaces
    Diego Ligtenberg| Rabobank

  7. Patterns and Anti-patterns of Agentic Engineering
    Victor Rentea| Independent Trainer



Fr 09.10.2026

  1. Agentic Engineering Workshop: Building Secure, Autonomous AI Agents and Multi-Agent Systems in Production
    Victor Rentea| Independent Trainer


https://www.youtube.com/@JAXLondonCon

 

01 October 2026

Gauss Billete

Billete antiguo de marcos alemanes del principe de las matematicas Carl Friedrich Gauss.






 

Blog Archive

Disclaimer

Qux