0

While trying to migrate my application from Java8,Springboot v1.x to Java21,Springboot v3.2.0, I encountered the following issue while trying to configure cassandra in my application:

> Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cassandraMappingContext' defined in class path resource [com/blabla/main/CassandraConfig.class]: Unable to make field private long java.util.GregorianCalendar.gregorianCutover accessible: module java.base does not "opens java.util" to unnamed module @61862a7f
> at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1775)
> at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
> at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523)
> at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325)
> at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
> at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323)
> at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:224)
> at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1321)
> at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1282)
> at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:484)
> at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:339)
> at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:332)
> at org.springframework.data.cassandra.config.AbstractSessionConfiguration.requireBeanOfType(AbstractSessionConfiguration.java:103)
> at org.springframework.data.cassandra.config.AbstractCassandraConfiguration.cassandraConverter(AbstractCassandraConfiguration.java:76)
> at com.blabla.main.CassandraConfig$$SpringCGLIB$$0.CGLIB$cassandraConverter$20(<generated>)
> at com.blabla.main.CassandraConfig$$SpringCGLIB$$FastClass$$0.invoke(<generated>)
> at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258)
> at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331)
> at com.blabla.main.CassandraConfig$$SpringCGLIB$$0.cassandraConverter(<generated>)
> at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
> at java.base/java.lang.reflect.Method.invoke(Method.java:580)
> at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140)
> 142 common frames omitted
> Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private long java.util.GregorianCalendar.gregorianCutover accessible: module java.base does not "opens java.util" to unnamed module @61862a7f
> at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:391)
> at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:367)
> at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:315)
> at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:183)
> at java.base/java.lang.reflect.Field.setAccessible(Field.java:177)
> at org.springframework.util.ReflectionUtils.makeAccessible(ReflectionUtils.java:804)
> at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.doWith(AbstractMappingContext.java:616)
> at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:728)
> at org.springframework.data.mapping.context.AbstractMappingContext.doAddPersistentEntity(AbstractMappingContext.java:471)
> at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:424)
> at org.springframework.data.cassandra.core.mapping.CassandraMappingContext.addPersistentEntity(CassandraMappingContext.java:326)
> at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.lambda$createAndRegisterProperty$3(AbstractMappingContext.java:671)
> at java.base/java.lang.Iterable.forEach(Iterable.java:75)
> at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.createAndRegisterProperty(AbstractMappingContext.java:668)
> at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.doWith(AbstractMappingContext.java:622)
> at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:728)
> at org.springframework.data.mapping.context.AbstractMappingContext.doAddPersistentEntity(AbstractMappingContext.java:471)
> at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:424)
> at org.springframework.data.cassandra.core.mapping.CassandraMappingContext.addPersistentEntity(CassandraMappingContext.java:326)
> at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.lambda$createAndRegisterProperty$3(AbstractMappingContext.java:671)
> at java.base/java.lang.Iterable.forEach(Iterable.java:75)
> at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.createAndRegisterProperty(AbstractMappingContext.java:668)
> at org.springframework.data.mapping.context.AbstractMappingContext$PersistentPropertyCreator.doWith(AbstractMappingContext.java:622)
> at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:728)
> at org.springframework.data.mapping.context.AbstractMappingContext.doAddPersistentEntity(AbstractMappingContext.java:471)
> at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:424)
> at org.springframework.data.cassandra.core.mapping.CassandraMappingContext.addPersistentEntity(CassandraMappingContext.java:326)
> at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:384)
> at java.base/java.lang.Iterable.forEach(Iterable.java:75)
> at org.springframework.data.cassandra.CassandraManagedTypes.forEach(CassandraManagedTypes.java:81)
> at org.springframework.data.mapping.context.AbstractMappingContext.initialize(AbstractMappingContext.java:563)
> at org.springframework.data.cassandra.core.mapping.CassandraMappingContext.initialize(CassandraMappingContext.java:114)
> at org.springframework.data.mapping.context.AbstractMappingContext.afterPropertiesSet(AbstractMappingContext.java:555)
> at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1822)
> at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1771)
> 163 common frames omitted

The CassandraConfig.java implementation:

@Configuration
@EnableCassandraRepositories(basePackages = "com.blabla")
public class CassandraConfig extends AbstractCassandraConfiguration {

  @Value("${cassandra.contactpoints}")
  private String contactPoints;

  @Value("${cassandra.port}")
  private int port;

  @Value("${cassandra.keyspace}")
  private String keySpace;

  @Value("${cassandra.basePackages}")
  private String basePackages;

  @Value("${cassandra.cluster}")
  private String clusterName;

  @Value("${cassandra.username}")
  private String username;
  
  @Value("${cassandra.consistency}")
  private String consistency;

  private String password;

  private static final Logger log = LoggerFactory.getLogger(CassandraConfig.class);

  @PostConstruct
  public void init(){
    // logic to get my password to connect with cassandra from another repo.
  }

  protected AuthProvider getAuthProvider() {
    return new PlainTextAuthProvider(username, password);
  }

  @Override
  protected String getKeyspaceName() {
    return keySpace;
  }

  @Override
  protected String getContactPoints() {
    return contactPoints;
  }

  @Override
  protected int getPort() {
    return port;
  }

  @Override
  public SchemaAction getSchemaAction() {
    return SchemaAction.CREATE_IF_NOT_EXISTS;
  }

  @Override
  public String[] getEntityBasePackages() {
    return new String[] {basePackages};
  }

  @Override
  protected String getClusterName() {
    return clusterName;
  }

  @Bean
  public QueryLogger queryLogger(Cluster cluster) {
    QueryLogger queryLogger = QueryLogger.builder().build();
    cluster.register(queryLogger);
    return queryLogger;
  }

  protected AddressTranslator getAddressTranslator() {
    return new CassandraAddressTranslator();
  }
  
  protected QueryOptions getQueryOptions() {
    QueryOptions queryOptions = new QueryOptions();
    queryOptions.setConsistencyLevel(ConsistencyLevel.valueOf(consistency));
    return queryOptions;
  }

}

I am using the following dependency for cassandra:

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-cassandra</artifactId>
    <version>4.3.3</version>
 </dependency>

I am unable to find the solution how my code can access the private field gregorianCutover from class GregorianCalendar.

At a number of places, I found a solution to use the following JVM arguments:

java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED

But I also got to know that this is not a safe and advisable approach to be followed.

Can someone please suggest a safe and clean approach to handle this issue?

I am using the latest version of all the dependencies.

2
  • 1
    Accessing a private field is never safe and clean. Later versions of Java are much stricter about preventing this misuse. GregorianCalendar has a public getGregorianChange method that returns the cutover value as a Date Commented Aug 30, 2024 at 19:02
  • 1
    I can’t imagine a reason to ever change this value, so you can simply assume it’s -12219292800000L all the time. Besides, it’s better to use the java.time API instead of the legacy Calendar anyway… Commented Sep 2, 2024 at 11:18

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.