-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
Expected behavior
Either LocalDateTime map(LocalDate date) results in compilation error or mapping results in date == null ? null : LocalDateTime.of(date, LocalTime.MIN)
Actual behavior
LocalDateTime map(LocalDate date) maps any date to null
The problem seems to be related to incorrect mapping sequence: LocalDate to XMLGregorianCalendar and XMLGregorianCalendar to LocalDateTime. Separately those mappings are correct, but combined are not:
Generated mapper contains the following line:
LocalDateTime localDateTime = xmlGregorianCalendarToLocalDateTime( localDateToXmlGregorianCalendar( date ) ); Generated method xmlGregorianCalendarToLocalDateTime(..) returns null if hours, minutes or seconds are equal to DatatypeConstants.FIELD_UNDEFINED, which they are cause localDateToXmlGregorianCalendar(..) calls javax.xml.datatype.DatatypeFactory::newXMLGregorianCalendarDate which sets hours, minuts, seconds and milliseconds as FIELD_UNDEFINED
Methods I'm talking about for reference:
private static LocalDateTime xmlGregorianCalendarToLocalDateTime( XMLGregorianCalendar xcal ) {
if ( xcal == null ) {
return null;
}
if ( xcal.getYear() != DatatypeConstants.FIELD_UNDEFINED
&& xcal.getMonth() != DatatypeConstants.FIELD_UNDEFINED
&& xcal.getDay() != DatatypeConstants.FIELD_UNDEFINED
&& xcal.getHour() != DatatypeConstants.FIELD_UNDEFINED
&& xcal.getMinute() != DatatypeConstants.FIELD_UNDEFINED
) { //some mapping }
return null;
}private XMLGregorianCalendar localDateToXmlGregorianCalendar( LocalDate localDate ) {
if ( localDate == null ) {
return null;
}
return datatypeFactory.newXMLGregorianCalendarDate(
localDate.getYear(),
localDate.getMonthValue(),
localDate.getDayOfMonth(),
DatatypeConstants.FIELD_UNDEFINED );
} public XMLGregorianCalendar newXMLGregorianCalendarDate(
final int year,
final int month,
final int day,
final int timezone) {
return newXMLGregorianCalendar(
year,
month,
day,
DatatypeConstants.FIELD_UNDEFINED, // hour
DatatypeConstants.FIELD_UNDEFINED, // minute
DatatypeConstants.FIELD_UNDEFINED, // second
DatatypeConstants.FIELD_UNDEFINED, // millisecond
timezone);
}Steps to reproduce the problem
Define Mapper:
@Mapper
public interface IssueBelkinmikeMapper {
IssueBelkinmikeMapper INSTANCE = Mappers.getMapper( IssueBelkinmikeMapper.class );
LocalDateTime map(LocalDate date);
}Define Test:
@WithClasses({
IssueBelkinmikeMapper.class
})
@IssueKey("belkinmike")
class IssueBelkinmikeMapperTest {
@ProcessorTest
void throwsException() {
LocalDate source = LocalDate.of(2022, 2, 2);
LocalDateTime target = IssueBelkinmikeMapper.INSTANCE.map(source);
assertThat(target).isNotNull();
}
}Test should pass or fail at mapper generation stage, but it is not
IMHO: It should fail at generating such mapping, cause I met this problem mapping dtos:
I had this classes
class EntityDto {
LocalDate dateFrom;
}
class Entity {
LocalDate dateFrom;
}
interface MyMapper {
EntityDto map(Entity e);
}then dto field's type changed to LocalDateTime:
class EntityDto {
LocalDateTime dateFrom;
}
class Entity {
LocalDate dateFrom;
}
interface MyMapper {
EntityDto map(Entity e);
}And I would expect mapping to fail and attract my attention to it, but it did not
MapStruct Version
main branch (commit id=a7ba12676d237957be0753076f436d7974c9f7f4)