1

I have an Instant field in my POJO class and want to set its value now() while creating record. As far as I see, MapStruct let this kind of feature, but I could not set it properly:

mapper:

@Mapper(componentModel = "spring", imports = {Instant.class})
public interface CreatePostRequestMapper {

    // @Mapping(target = "createdAt", defaultExpression ="java(Instant.now())")
    @Mapping(target = "createdAt", defaultValue = "java(Instant.now())")
    Post toEntity(CreatePostRequest source);

    CreatePostRequest toDto(Post destination);
}

And both classes has the same property with the same name:

private Instant createdAt;

Here is the service method:

private final CreatePostRequestMapper createPostRequestMapper;

public PostDetails createPost(@Valid CreatePostRequest request) {
    final Post post = createPostRequestMapper.toEntity(request);

    // code omitted
}

This gives the following error:

"Request processing failed; nested exception is java.time.format.DateTimeParseException: Text 'java(Instant.now())' could not be parsed at index 0] with root cause"

How can solve this?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161

1 Answers1

0

When you use defaultValue for Instant class, it will generate following code:

post.setCreatedAt( Instant.parse( "java(Instant.now())" ) );

And, obviously, Instant class cannot parse this string and create an object.

So, the right way is to use defaultExpression, this will generate following code:

post.setCreatedAt( Instant.now() );

The difference is noticeable :)

Hope it will help you.

Max Aminov
  • 357
  • 4
  • 8
  • Very good. On the other hand, d you have an idea for setting Instant globally? This works for DateTime, but cannot implement it for Instant. Any idea --> –  Feb 26 '23 at 13:02
  • `@Configuration public class AppConfig { @Bean public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { return builder -> { builder.simpleDateFormat(DATE_TIME_FORMAT); builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_FORMAT))); builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT))); // not working >>> builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT).withZone(ZoneId.systemDefault()))); }; } }` –  Feb 26 '23 at 13:04
  • Do you mean, how to setup a configuration to serialize Instant field in a proper DATE_TIME_FORMAT string format? – Max Aminov Feb 26 '23 at 13:09
  • In my Spring Boot project, I can format LocalDate and LocalDateTime with that global config. I also want to format my Instant field in DATE_TIME_FORMAT, but could not find a proper parameters (the serializer method takes different parameters): –  Feb 26 '23 at 13:21
  • Looked up in the library and I do not know why, but class InstantSerializer has only protected constructors. Currently, I can only recommend you manually add @JsonSerialize annotation to every Instant field – Max Aminov Feb 26 '23 at 13:53