8

I am new in Mapstruct. I have a model object which includes LocalDateTime type field. DTO includes Instant type field. I want to map LocalDateTime type field to Instant type field. I have TimeZone instance of incoming requests.

Manually field setting like that;

set( LocalDateTime.ofInstant(x.getStartDate(), timeZone.toZoneId()) )

How can I map these fields using with Mapstruct?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Batuhan
  • 463
  • 2
  • 6
  • 22

1 Answers1

18

You have 2 options to achieve what you are looking for.

First option:

Use the new @Context annotation from 1.2.0.Final for the timeZone property and define your own method that would perform the mapping. Something like:

public interface MyMapper {

    @Mapping(target = "start", source = "startDate")
    Target map(Source source, @Context TimeZone timeZone);

    default LocalDateTime fromInstant(Instant instant, @Context TimeZone timeZone) {
        return instant == null ? null : LocalDateTime.ofInstant(instant, timeZone.toZoneId());
    }
}

MapStruct will then use the provided method to perform mapping between Instant and LocalDateTime.

The second option:

public interface MyMapper {

    @Mapping(target = "start", expression = "java(LocalDateTime.ofInstant(source.getStartDate(), timezone.toZoneId()))")
    Target map(Source source, TimeZone timeZone);
}

My personal option would be to use the first one

Tarek Badr
  • 847
  • 9
  • 12
Filip
  • 19,269
  • 7
  • 51
  • 60
  • 1
    Thank you Filip, I created a class which includes first option methods (fromInstant and toInstant). I referenced this class to my mapper (@Mapper(uses=LocalTimeMapper.class)). Thanks again. – Batuhan Dec 24 '17 at 10:27
  • That's even better as it allows for better usability. For other readers all default methods can be done in another class(es) and be referenced via `Mapper#uses` – Filip Dec 24 '17 at 10:33
  • Absolutely I agree. I have a question about to use Mapstruct mapper as spring bean. When i use componentModel='spring", mapper will be a singleton class.(generated class annotated with @Component). Could there be any performance issue on multi thread requests? To inject mapper as singleton bean or to initialize mapper instance every time ( Mappers.getMapper( XMapper.class ); ), What is your preference ? – Batuhan Dec 24 '17 at 10:48
  • Best would be to direct such questions in our chat. In any case using it as a spring bean has no performance hit, using the mappers factory on each request is actually not recommended. Our recommendation, in case you dont want to use dependency injection, is to assign the mapper to some static final field which you would then use everywhere. However, me personally use spring and inject the mappers where they are needed, it is easier for testing purposes as well – Filip Dec 24 '17 at 12:03
  • Ok, i changed my usage to bean injection, thanks Filip for your helpful answers. – Batuhan Dec 24 '17 at 13:14
  • I used it for sql timestamp datatype: `default LocalDateTime fromTimestamp(Timestamp sqlTimestamp)`. Thanks – Lucas Nov 14 '20 at 00:36
  • In version 1.1.0 of mapstruct that @Context is not exists, you can use `ZoneId.systemDefault()` – Ali Sohrabi Jan 09 '23 at 12:20