Uploaded image for project: 'Spring Data Elasticsearch'
  1. Spring Data Elasticsearch
  2. DATAES-614

Repository query define date input parameter format or match the configured one

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Minor
    • Resolution: Won't Fix
    • Affects Version/s: 3.2 RC1 (Moore)
    • Fix Version/s: None
    • Component/s: None
    • Environment:
      Elasticsearch 6.5.3, Spring Boot 2.1.6, Jackson 2.9.0

      Description

      I am using Elasticsearch 6.5.3 and Spring Boot 2.1.6 and spring-data-elasticsearch 3.2.0.M1.

      I have defined the Elasticsearch configuration to use Jackson JavaTimeModule as:

       

       

       

      @Bean
      public ElasticsearchOperations elasticsearchTemplate() {
          return new ElasticsearchRestTemplate(client(), new CustomEntityMapper());
      }
      
      public static class CustomEntityMapper implements EntityMapper {
      
          private final ObjectMapper objectMapper;
      
          public CustomEntityMapper() {
              //we use this so that Elasticsearch understands LocalDate and LocalDateTime objects
              objectMapper = new ObjectMapper()
                                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
                                .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
                                .disable(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)
                                .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                                //MUST be registered BEFORE calling findAndRegisterModules
                                .registerModule(new JavaTimeModule())
                                .registerModule(new Jdk8Module());
              //only autodetect fields and ignore getters and setters for nonexistent fields when serializing/deserializing
              objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker()
                              .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                              .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                              .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                              .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
              //load the other available modules as well
              objectMapper.findAndRegisterModules();
          }
      
          @Override
          public String mapToString(Object object) throws IOException {
              return objectMapper.writeValueAsString(object);
          }
      
          @Override
          public <T> T mapToObject(String source, Class<T> clazz) throws IOException {
              return objectMapper.readValue(source, clazz);
          }
      }
      

       

       

      And I have defined a repository with a method as:

      {}

      
      

      List<AccountDateRollSchedule> findAllByNextRollDateTimeLessThanEqual(final LocalDateTime dateTime);

      {{}}

       

      {}

      And the POJO AccountDateRollSchedule defines that field as:

       

      {{{{ }}}}

      
      

      {{@Field(type = FieldType.Date, format = DateFormat.date_hour_minute) @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm") }}
      @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm") private LocalDateTime nextRollDateTime;

      {{}}

       

      {{}}

      I see my index properly has that field created as declared and expected:

      {}

      
      

      {{"nextRollDateTime":

      { "type": "date", "format": "date_hour_minute" }

      }}

      {{}}

       

      {}

      Also querying the index returns the field formatted as expected:

      {}

      
      

      "nextRollDateTime" : "2019-06-27T13:34"

      {{}}

       

       

       

      Passing any LocalDateTime input to the method does NOT respect the format defined for the field, the FULL format is always used instead. For example invoking:

       

      {{findAllByNextRollDateTimeLessThanEqual(LocalDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.MINUTES));}}

      {}

      gives me the following exception (any @DateTimeFormat or @JsonFormat annotation on the method parameter in the repository is ignored):

       

      {}

      Unrecognized chars at the end of [2019-07-22T09:07:00.000]: [:00.000]

      {}

       

      If I instead change the repository method to accept a String and pass a String formatted exactly as expected as input to it, it works no problem.

       

      In fact, it looks like LocalDateTime is not handled at all and a String should be used instead because changing the field definition to:

      @Field(type = FieldType.Date, format = DateFormat.date_hour_minute_second_fraction)
      @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS")
      @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS")
      private LocalDateTime nextRollDateTime;

       

      Which is exactly the full format of the LocalDateTime object as a String, I still get an error:

       

      Invalid format: "2019-07-22T09:56:00.000" is malformed at ":00.000"

       

      Is it possible to somehow define the format used for the date parameter passed in input to the repository method or have Spring use the one configured on the field itself?

       

      I would like not to wrap that method for a simple conversion like this (I did and it works), and I would also like to avoid using long type for the date field

      Thanks and cheers

        Attachments

          Activity

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            grog Stefano Ghio
            Last updater:
            Spring Issues Spring Issues
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: