Multi-module Project, Record, Interface Behaviour
Expected behavior
@Generated( value = "org.mapstruct.ap.MappingProcessor", date = "2024-08-12T10:53:53-0400", comments = "version: 1.5.5.Final, compiler: javac, environment: Java 21.0.4 (Ubuntu)" ) class RecordInterfaceIssueMapperImpl implements RecordInterfaceIssueMapper { @Override public TargetRootRecord map(SourceRootRecord source) { if ( source == null ) { return null; } TargetNestedRecord nested = null; nested = sourceNestedRecordToTargetNestedRecord( source.nested() ); TargetRootRecord targetRootRecord = new TargetRootRecord( nested ); return targetRootRecord; } @Override public SourceRootRecord map(TargetRootRecord target) { if ( target == null ) { return null; } SourceNestedRecord nested = null; nested = targetNestedRecordToSourceNestedRecord( target.nested() ); SourceRootRecord sourceRootRecord = new SourceRootRecord( nested ); return sourceRootRecord; } protected TargetNestedRecord sourceNestedRecordToTargetNestedRecord(SourceNestedRecord sourceNestedRecord) { if ( sourceNestedRecord == null ) { return null; } String field = null; field = sourceNestedRecord.field(); TargetNestedRecord targetNestedRecord = new TargetNestedRecord( field ); return targetNestedRecord; } protected SourceNestedRecord targetNestedRecordToSourceNestedRecord(TargetNestedRecord targetNestedRecord) { if ( targetNestedRecord == null ) { return null; } String field = null; field = targetNestedRecord.field(); SourceNestedRecord sourceNestedRecord = new SourceNestedRecord( field ); return sourceNestedRecord; } }
Actual behavior
@Generated( value = "org.mapstruct.ap.MappingProcessor", date = "2024-08-12T10:55:11-0400", comments = "version: 1.5.5.Final, compiler: javac, environment: Java 21.0.4 (Ubuntu)" ) class RecordInterfaceIssueMapperImpl implements RecordInterfaceIssueMapper { @Override public TargetRootRecord map(SourceRootRecord source) { if ( source == null ) { return null; } TargetNestedRecord nested = null; nested = nestedInterfaceToTargetNestedRecord( source.nested() ); TargetRootRecord targetRootRecord = new TargetRootRecord( nested ); return targetRootRecord; } @Override public SourceRootRecord map(TargetRootRecord target) { if ( target == null ) { return null; } SourceNestedRecord nested = null; nested = targetNestedRecordToSourceNestedRecord( target.nested() ); SourceRootRecord sourceRootRecord = new SourceRootRecord( nested ); return sourceRootRecord; } protected TargetNestedRecord nestedInterfaceToTargetNestedRecord(NestedInterface nestedInterface) { if ( nestedInterface == null ) { return null; } String field = null; TargetNestedRecord targetNestedRecord = new TargetNestedRecord( field ); return targetNestedRecord; } protected SourceNestedRecord targetNestedRecordToSourceNestedRecord(TargetNestedRecord targetNestedRecord) { if ( targetNestedRecord == null ) { return null; } String field = null; field = targetNestedRecord.field(); SourceNestedRecord sourceNestedRecord = new SourceNestedRecord( field ); return sourceNestedRecord; } }
Steps to reproduce the problem
This occurs when the following 3 things are combined:
SourceandTargettypes are in difference modules (e.g. a multi-module Maven project)- Records are used for the
SourceandTargettypes - The
Sourcerecords implement interfaces
Example
interface RootInterface { NestedInterface nested(); } interface NestedInterface { String field(); } record SourceRootRecord( SourceNestedRecord nested ) implements RootInterface { } record SourceNestedRecord( String field ) implements NestedInterface { }
Module 2 (depends on Module 1)
@Mapper interface RecordInterfaceIssueMapper { TargetRootRecord map(SourceRootRecord source); SourceRootRecord map(TargetRootRecord target); } record TargetRootRecord( TargetNestedRecord nested ) { } record TargetNestedRecord( String field ) { }
Test
class RecordInterfaceIssueTest { RecordInterfaceIssueMapper mapper; SourceRootRecord source; TargetRootRecord target; @BeforeEach void setUp() { mapper = Mappers.getMapper(RecordInterfaceIssueMapper.class); source = new SourceRootRecord(new SourceNestedRecord("field")); target = new TargetRootRecord(new TargetNestedRecord("field")); } @Test void testMap_Source() { // This fails assertThat(mapper.map(source)).isEqualTo(target); } @Test void testMap_Target() { // This succeeds assertThat(mapper.map(target)).isEqualTo(source); } }
MapStruct Version
1.5.5.Final