21

I'm trying to make a method, which uses the Json data with jackson library to have a list of objects. If I run my code, I get the error:

java.lang.reflect.InaccessibleObjectException: Unable to make field private final int java.time.LocalDate.year accessible: module java.base does not "opens java.time" to unnamed module @5c90e579

Why is it giving me an error about LocalDate even though I have JodaModul in my Code?

public static List<Tweet> getTweetsFile() throws Exception{

            ObjectMapper mapper = new ObjectMapper().
                    registerModule(new JodaModule()).
                    configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
            
            File path = new File ("C:/Users/PC/eclipse-workspace/hw4/tw.json");

            List<Tweet> myObjects3 =  Arrays.asList(mapper.readValue(path, Tweet.class));
    
            return myObjects3;
    }

How it looks in my File:

[{"date":"2001-12-28","tweetNumber":1,"country":"England","comments":11,"message":"I like to watch anime and reading books","retweets":3,"username":"Isabelle","likes":55},{"date":"2003-05-11","tweetNumber":2,"country":"France","comments":25,"message":"I'm Viatnamese, but I live in France","retweets":30,"username":"Vin","likes":110}..

It's not in the right order like my Object has in their constructor, could that be the reaseon?

VGR
  • 40,506
  • 4
  • 48
  • 63
  • Do you use the latest version of jackson? – dan1st Dec 19 '21 at 16:22
  • In _Project > Properties: Java Build Path_ tab _Module Dependencies_ select the `java.base` module and click _Expose Package..._ button. Enter as _Package_ `java.time`, as _Target module_ `UNNAMED` and select _opens_. Does this fix your issue? But probably the root cause is that you use a too old library that was written for an older Java version. So first check, if your used libraries are up to date. – howlger Dec 19 '21 at 17:24
  • I got it now, default constructor was missing and I had a mistake in it and yes I had to use JavaTime for it. Thanks –  Dec 20 '21 at 15:19

9 Answers9

26

You can fix this issue on your own.

add --add-opens java.base/java.time=ALL-UNNAMED as start-argument and it'll work.

Here is the corresponding JEP

makson
  • 1,975
  • 3
  • 23
  • 31
  • if you are on Windows, use `--add-opens=java.base/java.time=ALL-UNNAMED` for `JAVA_TOOL_OPTIONS` environment variable. – Imran May 24 '22 at 16:20
5

In STS or eclipse add the folowing statement in default VM arguments

--add-opens java.base/java.time=ALL-UNNAMED

Default VM arguments path: Window -> Preferences -> Installed JREs -> select jre -> edit

chetan
  • 51
  • 1
  • 2
3

I used this way and fixed this Problem. Firstly you have to create LocalDateTime Deserializer with the given Date Format in your Json Data.

class LocalDateTimeDeserializer implements JsonDeserializer < LocalDateTime > {
@Override
public LocalDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
    return LocalDateTime.parse(json.getAsString(),
        DateTimeFormatter.ofPattern("d::MMM::uuuu HH::mm::ss").withLocale(Locale.ENGLISH));
}

}

Then create Object of Type GsonBuilder and adapt it with your LocalDateDeserializer.

gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeDeserializer());

Gson gson = gsonBuilder.setPrettyPrinting().create();
2

I got this exception with JDK 17 and Gson:

Unable to make field private final java.time.LocalDate java.time.LocalDateTime.date accessible: module java.base does not "opens java.time"

so I used this custom TypeAdapter with null checks:

public class LocalDateTimeTypeAdapter extends TypeAdapter<LocalDateTime> {

    @Override
    public void write(final JsonWriter jsonWriter, final LocalDateTime localDate) throws IOException {
        if (localDate == null) {
            jsonWriter.nullValue();
            return;
        }
        jsonWriter.value(localDate.toString());
    }

    @Override
    public LocalDateTime read(final JsonReader jsonReader) throws IOException {
        if (jsonReader.peek() == JsonToken.NULL) {
            jsonReader.nextNull();
            return null;
        }
        return ZonedDateTime.parse(jsonReader.nextString()).toLocalDateTime();
    }
}
nbarm
  • 21
  • 3
1

From my reading of this issue, the problems that required you to do the "--add-opens" hack or other work-arounds should be fixed in current Jackson releases.

So, if you are still finding you need to do this:

  1. Make sure you are using a recent Jackson release1.
  2. If that doesn't help, raise a Jackson issue which sufficient specificity to allow the Jackson developers to figure out where this instance of the problem is occuring.

The "--add-opens" approach will work, but it is not a good solution. The good solution is to help the developers to fix the problem by reporting it.


1 - I can't give you a specific release because it is not clear from the issue tracker or release notes precisely when the problem(s) were fixed. But 2.14.0 or later seems like a good bet, based on the date of the issue closure.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

I got this error after upgrading the application to Java 17 and Spring Boot 3. Adding VM options will lead to other problems.

1.Fixed by adding the adapter.

 public class LocalDateTypeAdapter
    implements JsonSerializer<LocalDate>, JsonDeserializer<LocalDate> {

  private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

  @Override
  public JsonElement serialize(final LocalDate date, final Type typeOfSrc,
      final JsonSerializationContext context) {
    return new JsonPrimitive(date.format(formatter));
  }

  @Override
  public LocalDate deserialize(final JsonElement json, final Type typeOfT,
      final JsonDeserializationContext context) throws JsonParseException {
    return LocalDate.parse(json.getAsString(), formatter);
  }
}

2.Then register the adapter like this :-

@Configuration
public class GsonConfiguration {

    @Bean
    public GsonBuilderCustomizer typeAdapterRegistration() {
        return builder -> {
            builder.registerTypeAdapter(LocalDate.class, new LocalDateTypeAdapter());
        };
    }
}
Tushar Wasson
  • 494
  • 5
  • 10
0

I encountered a similar issue when I was unit testing Twilio SMS.

I solved the issue by registering JavaTimeModule on the ObjectMapper.

        String json = "{\"status\": \"sent\"}";
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        var message = Message.fromJson(json, mapper);
Ken
  • 1
  • 1
0

You can always use additional DTO object with already parsed LocalDate to String.

Lukk17s
  • 986
  • 10
  • 11
-8

I solved this problem to change jdk16 to jdk11.

necmiye
  • 23
  • 2
    You haven't solved it. You have just put off the problem so that it can come back and bite you when you move to Java 17 (or later). – Stephen C Nov 13 '22 at 23:28