Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Non-deterministic code generation (SourceTargetMapperImpl.java) #3940

@Fr4nk03

Description

@Fr4nk03

Expected behavior

Summary

The processor test suite (mapstruct/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time) contains tests that fail intermittently due to non-deterministic behavior in the code generation process. These issues were discovered using the NonDex tool. The root causes are related to iterating over collections with no guaranteed order, such as method lists from the compiler and HashSets.

Root Cause Analysis

Unstable Field Order: The MapperRetrievalProcessor iterates through each ExecutableElement from elementUtils.getAllEnclosedExecutableElements() to add method into List. However, getAllEnclosedExecutableElements is implemented using a HashSet which the order is not guaranteed to be stable. The processor then discovers and creates the required DateTimeFormatter fields in this unstable order, leading to a non-deterministic layout in the final generated file.

Potential Fix

  1. I will open a pull request for modification of the comparing logic in JavaFileAssert.java by sorting the fields in both files to make the comparison more robust.
  2. A more fundamental and valuable alternative would be to make the code generation itself predictable. It can be fixed by sorting the list of methods right after they are retrieved from the compiler, before any processing happens.

Actual behavior

Unstable Field Order in Generated Mappers

The order of helper fields (specifically DateTimeFormatter fields) in the generated mapper implementation classes is not consistent across builds.

  • Run 1 Output:

    private final DateTimeFormatter dateTimeFormatter_dd_MM_yyyy_HH_mm_12071769242 = ...
    private final DateTimeFormatter dateTimeFormatter_HH_mm_168697690 = ...
  • Internal Field Order (from debug print):

    ----- Fields Order -----
    SupportingField@2e6109be
    SupportingField@12251427
    SupportingField@aa6b84f3
    SupportingField@3e07ade
    
  • Run 2 Output:

    private final DateTimeFormatter dateTimeFormatter_HH_mm_168697690 = ...
    private final DateTimeFormatter dateTimeFormatter_dd_MM_yyyy_HH_mm_12071769242 = ...
  • Internal Field Order (from debug print):

    ----- Fields Order -----
    SupportingField@12251427
    SupportingField@2e6109be
    SupportingField@3e07ade
    SupportingField@aa6b84f3
    
    

Steps to reproduce the problem

This non-deterministic behavior can be reliably reproduced by running the NonDex Maven plugin on the processor module.

  1. Navigate to the root of the MapStruct project.
  2. Run the following command:
    mvn -pl processor edu.illinois:nondex-maven-plugin:2.2.1:nondex
  3. Observe that the build will fail intermittently on tests like Java8CustomPatternDateTimeFormatterGeneratedTesteach

MapStruct Version

MapStruct 1.7.0-SNAPSHOT

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions