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

Illegal reflective access by com.fasterxml.jackson.databind.util.ClassUtil to field java.time.format.DateTimeFormatter.locale #2626

Closed
abstractionmage opened this issue Feb 20, 2020 · 6 comments
Labels
JDK11 Features that need JDK11 (and/or support JDK11)

Comments

@abstractionmage
Copy link

I could provoke this error by trying to serialize an ISO compliant Datetime String into a Java object of type DateTimeFormatter. I promise I won't do it again, but maybe you're still interested in both the full error message and how I got it to pop up.

error message:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.fasterxml.jackson.databind.util.ClassUtil (file:/C:/Users/Xrenyn/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.9.9/jackson-databind-2.9.9.jar) to field java.time.format.DateTimeFormatter.locale
WARNING: Please consider reporting this to the maintainers of com.fasterxml.jackson.databind.util.ClassUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2020-02-20 15:10:33.695  WARN 10168 --- [io-10000-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `de.hsa.bildschweinerkennung.DateTime` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"timeSent": "2020-02-09T21:39:15+01:00"}'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `de.hsa.bildschweinerkennung.DateTime` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"timeSent": "2020-02-09T21:39:15+01:00"}')
 at [Source: (PushbackInputStream); line: 1, column: 1]]

How I got there:

First, I've set up a REST Controller using Spring Boot v2.1.6.RELEASE like this:

@RestController
public class RESTController {
    public static void main(String[] args) {
        SpringApplication.run(RESTController.class, args);
    }
    @PostMapping(value = "/receiveDateTime", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public DateTime receiveDateTime(@RequestBody DateTime dateTime){
        return dateTime;
    }
}

Up above, DateTime is a custom data class for holding a single DateTimeFormatter like so:

public class DateTime {
    private DateTimeFormatter dateTime;

    public DateTime() {}

    public DateTimeFormatter getDateTime() {
        return dateTime;
    }

    public void setDateTime(DateTimeFormatter dateTime) {
        this.dateTime = dateTime;
    }
}

Now I just have to send a POST request to the /receiveDateTime mapping as I did with those two lines of Python code:

json_data = json.dumps({"timeSent": "2020-02-09T21:39:15+01:00"})
response = requests.post(url="http://localhost:10000/receiveDateTime", json=json_data)

The response is a 400 error code by the way, looking like that:

b'{"timestamp":"2020-02-20T14:35:59.797+0000","status":400,"error":"Bad Request","message":"JSON parse error: Cannot construct instance of `de.hsa.bildschweinerkennung.DateTime` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value (\'{\\"timeSent\\": \\"2020-02-09T21:39:15+01:00\\"}\'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `de.hsa.bildschweinerkennung.DateTime` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value (\'{\\"timeSent\\": \\"2020-02-09T21:39:15+01:00\\"}\')\\n at [Source: (PushbackInputStream); line: 1, column: 1]","path":"/receiveDateTime"}'
@cowtowncoder
Copy link
Member

Thanks! This is sort of useful -- it already made sense that the warning comes from introspection, trying to access something that Java 9+ module system would block.

Question of what to do with DateTimeFormatter is interesting too; could either explicitly throw exception for unsupported type, or, if feasible add "to/from-String" handlers.

@cowtowncoder cowtowncoder added the JDK11 Features that need JDK11 (and/or support JDK11) label Mar 16, 2020
@agongi
Copy link

agongi commented Apr 7, 2020

Hello, The similar one happened to method java.time.ZoneRegion.getId() also.

Here are clauses.

@Test
public void exceptionExpectJSR310DateTypes() {
    var mapper = new ObjectMapper();
    // given
    VarietyDateType dateType = VarietyDateType.builder()
        .localDateTime(LocalDateTime.now())
        .localDate(LocalDate.now())
        .localTime(LocalTime.now())
        .zonedDateTime(ZonedDateTime.now(ZoneId.of("UTC")))
        .duration(Duration.ofDays(1))
        .instant(Instant.now())
        .build();

    // when
    Assertions.assertThatThrownBy(() -> {
        // ser
        String serialized = mapper.writeValueAsString(dateType);
        // des - exception
        mapper.readValue(serialized, VarietyDateType.class);
    }).isInstanceOf(InvalidDefinitionException.class)
        // then
        .hasMessageContaining("no Creators, like default construct, exist");
}

@Value
@Builder
static class VarietyDateType {
    private LocalDateTime localDateTime;
    private LocalDate localDate;
    private LocalTime localTime;

    private ZonedDateTime zonedDateTime;
    private Instant instant;
    private Duration duration;
}

and the warning comes to console.

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.fasterxml.jackson.databind.util.ClassUtil (file:/Users/user/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-databind/2.10.2/528de95f198afafbcfb0c09d2e43b6e0ea663ec/jackson-databind-2.10.2.jar) to method java.time.ZoneRegion.getId()
WARNING: Please consider reporting this to the maintainers of com.fasterxml.jackson.databind.util.ClassUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

@cowtowncoder
Copy link
Member

@agongi Right, since you did not register Java 8 date time module, and as such all types from within are handled as Beans.

I think I will actually file a separate issue for trying to see if I could improve exception message for such cases (essentially looking at ser/deser of types java.time.* in absence of registered (de)serializers).

@arick
Copy link

arick commented Sep 20, 2020

I am getting this message when I am serializing/dserializing a LocalDate object, using a set of custom serializer and deserializer classes. But, interesting enough, when I added "@JsonIgnore" to three setter methods, that happen to use a different DateTimeFormatter instance, the error messages went away.

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.fasterxml.jackson.databind.util.ClassUtil (file:/Users/arick/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.9.8/jackson-databind-2.9.8.jar) to field java.time.LocalDate.year
WARNING: Please consider reporting this to the maintainers of com.fasterxml.jackson.databind.util.ClassUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
public class MainClass {
...
   @JsonDeserialize(using = LocalDateDeserializer.class)
   @JsonSerialize(using = LocalDateSerializer.class)
   @JsonProperty("MeetingID")
   private LocalDate meetingID;
...
}
public class LocalDateDeserializer extends StdDeserializer<LocalDate> {
   static public final DateTimeFormatter meetingIDFormatter    = DateTimeFormatter.ofPattern("yyyyMMdd");
   protected LocalDateDeserializer() {
      super(LocalDate.class);
   }
   @Override
   public LocalDate deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
      return LocalDate.parse(jsonParser.readValueAs(String.class), meetingIDFormatter);
   }
public class LocalDateSerializer extends StdSerializer<LocalDate> {
   static public final DateTimeFormatter meetingIDFormatter    = DateTimeFormatter.ofPattern("yyyyMMdd");
   public LocalDateSerializer(){
       super(LocalDate.class);
   }
   @Override
   public void serialize(LocalDate value, JsonGenerator generator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
       generator.writeString(value.format(meetingIDFormatter));
   }
}

@cowtowncoder
Copy link
Member

@arick I suspect that registering (de)serializer(s) using module (like SimpleModule.addDeserializer()/addSerializer()) might avoid triggering of the issue. Unfortunately warning does not indicate specific access method considered problematic.

@cowtowncoder
Copy link
Member

Not sure what could be done here: Jackson 2.12 at least checks for missing module (see #2683 ).
So closing for now; may re-file with situation against 2.12, improvement ideas -- there is likely to general solution for these warnings, but it should be possible to address specific cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JDK11 Features that need JDK11 (and/or support JDK11)
Projects
None yet
Development

No branches or pull requests

4 participants