Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repository query define date input parameter format or match the configured one [DATAES-614] #1187

Closed
spring-projects-issues opened this issue Jul 22, 2019 · 1 comment
Labels
status: declined type: bug

Comments

@spring-projects-issues
Copy link

spring-projects-issues commented Jul 22, 2019

Stefano Ghio opened DATAES-614 and commented

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


Affects: 3.2 RC1 (Moore)

Reference URL: https://stackoverflow.com/questions/56792706/spring-data-elasticsearch-repository-query-define-date-input-parameter-format

@spring-projects-issues
Copy link
Author

spring-projects-issues commented Jan 31, 2020

sothawo commented

Please see my answer on the linked SO question. For the upcoming version 4.0 we have a total rewrite of the internal process of mapping and field processing, so there these problems do not exist anymore.

The changes to fix the method argument processing cannot be backported as they depend on the internal refactorings and rewritings.

So, alas, you will have to do some workingaround like you described on SO

@spring-projects-issues spring-projects-issues added type: bug status: declined labels Dec 31, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined type: bug
Projects
None yet
Development

No branches or pull requests

1 participant