Skip to content

JPMS: export to spring.core required #33373

@xenoterracide

Description

@xenoterracide

This is hopefully just a lack of understanding on how spring "cglib" support is supposed to work (in quotes because it's not cglib anymore right?) or how exactly a reflective access needs exports instead of just opens. Sorry if this isn't simply an understanding problem vs an issue which could be fixed to allow my module to work without adding an exports ... to spring...

// © Copyright 2024 Caleb Cushing
// SPDX-License-Identifier: AGPL-3.0-or-later

package com.xenoterracide.jpa.transaction;

import com.xenoterracide.jpa.annotation.TransactionScope;
import com.xenoterracide.jpa.util.Constants;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import org.jspecify.annotations.NonNull;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.support.SimpleTransactionScope;

/**
 * The type Transaction bean post processor.
 */
@Configuration
class TransactionBeanPostProcessor implements BeanFactoryPostProcessor {

  private static final ZoneId UTC = ZoneId.of("UTC");

  @Bean
  @TransactionScope
  Instant instantNow() {
    return Instant.now();
  }

  @Bean
  @TransactionScope
  ZonedDateTime zonedDateTimeNow(@NonNull Instant instantNow) {
    return instantNow.atZone(UTC);
  }

  /**
   * Offset date time now offset date time.
   *
   * @param zonedDateTimeNow the zoned date time now
   * @return the offset date time
   */
  @Bean
  @TransactionScope
  OffsetDateTime offsetDateTimeNow(@NonNull ZonedDateTime zonedDateTimeNow) {
    return zonedDateTimeNow.toOffsetDateTime();
  }

  @Override
  public void postProcessBeanFactory(@NonNull ConfigurableListableBeanFactory beanFactory) throws BeansException {
    beanFactory.registerScope(Constants.TRANSACTION_SCOPE, new SimpleTransactionScope());
  }
}
import org.jspecify.annotations.NullMarked;

/**
 * JPA utilities.
 */
@NullMarked module com.xenoterracide.jpa {
  exports com.xenoterracide.jpa;
  exports com.xenoterracide.jpa.annotation;
  exports com.xenoterracide.jpa.util;
  opens com.xenoterracide.jpa to org.hibernate.orm.core, spring.core;
  opens com.xenoterracide.jpa.transaction to spring.core;

  requires java.base;
  requires org.apache.commons.lang3;
  requires spring.data.commons;
  requires spring.beans;
  requires spring.context;
  requires spring.tx;
  requires org.hibernate.orm.envers;

  requires static transitive org.jspecify;
  requires static com.xenoterracide.tools.java;
  requires static jakarta.annotation;
  requires transitive jakarta.persistence;
  requires transitive jakarta.validation;
  requires transitive com.xenoterracide.model;
}

Adding this fixes it.

  exports com.xenoterracide.jpa.transaction to spring.beans, spring.context;
    Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.xenoterracide.jpa.transaction.TransactionBeanPostProcessor$$SpringCGLIB$$0]: Is the constructor accessible?

    	at [email protected]/org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.11.jar:?]
    	at [email protected]/org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.11.jar:?]
    	at [email protected]/org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:202) ~[spring-context-6.1.11.jar:?]
    	at [email protected]/org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:789) ~[spring-context-6.1.11.jar:?]
    	at [email protected]/org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:607) ~[spring-context-6.1.11.jar:?]
    	at [email protected]/org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.2.jar:?]
    	at [email protected]/org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.2.jar:?]
    	at [email protected]/org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.2.jar:?]
    	at [email protected]/org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137) ~[spring-boot-test-3.3.2.jar:?]
    	at [email protected]/org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58) ~[spring-core-6.1.11.jar:?]
    	at [email protected]/org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46) ~[spring-core-6.1.11.jar:?]
    	at [email protected]/org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1463) ~[spring-boot-3.3.2.jar:?]
    	at [email protected]/org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:553) ~[spring-boot-test-3.3.2.jar:?]
    	at [email protected]/org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137) ~[spring-boot-test-3.3.2.jar:?]
    	at [email protected]/org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108) ~[spring-boot-test-3.3.2.jar:?]
    	at [email protected]/org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225) ~[spring-test-6.1.11.jar:?]
    	at [email protected]/org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152) ~[spring-test-6.1.11.jar:?]
    	... 130 more
    Caused by: java.lang.IllegalAccessException: class org.springframework.beans.BeanUtils (in module spring.beans) cannot access class com.xenoterracide.jpa.transaction.TransactionBeanPostProcessor$$SpringCGLIB$$0 (in module com.xenoterracide.jpa) because module com.xenoterracide.jpa does not export com.xenoterracide.jpa.transaction to module spring.beans

    Caused by: java.lang.IllegalAccessException: class org.springframework.beans.BeanUtils (in module spring.beans) cannot access class com.xenoterracide.jpa.transaction.TransactionBeanPostProcessor$$SpringCGLIB$$0 (in module com.xenoterracide.jpa) because module com.xenoterracide.jpa does not export com.xenoterracide.jpa.transaction to module spring.beans
    	at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:394) ~[?:?]
    	at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:714) ~[?:?]
    	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:495) ~[?:?]
    	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486) ~[?:?]
    	at [email protected]/org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:195) ~[spring-beans-6.1.11.jar:?]
    	at [email protected]/org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:94) ~[spring-beans-6.1.11.jar:?]
    	at [email protected]/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1331) ~[spring-beans-6.1.11.jar:?]
    	at [email protected]/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) ~[spring-beans-6.1.11.jar:?]
    	at [email protected]/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.11.jar:?]
    	at [email protected]/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.11.jar:?]
    	at [email protected]/org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.11.jar:?]
    	at [email protected]/org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.11.jar:?]
    	at [email protected]/org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.11.jar:?]
    	at [email protected]/org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.11.jar:?]
    	at [email protected]/org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:202) ~[spring-context-6.1.11.jar:?]
    	at [email protected]/org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:789) ~[spring-context-6.
    1.11.jar:?]
    	at [email protected]/org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:607) ~[spring-context-6.1.11.jar:?]
    	at [email protected]/org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.2.jar:?]
    	at [email protected]/org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.2.jar:?]
    	at [email protected]/org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.2.jar:?]
    	at [email protected]/org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137) ~[spring-boot-test-3.3.2.jar:?]
    	at [email protected]/org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58) ~[spring-core-6.1.11.jar:?]
    	at [email protected]/org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46) ~[spring-core-6.1.11.jar:?]
    	at [email protected]/org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1463) ~[spring-boot-3.3.2.jar:?]
    	at [email protected]/org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:553) ~[spring-boot-test-3.3.2.jar:?]
    	at [email protected]/org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137) ~[spring-boot-test-3.3.2.jar:?]
    	at [email protected]/org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108) ~[spring-boot-test-3.3.2.jar:?]
    	at [email protected]/org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225) ~[spring-test-6.1.11.jar:?]
    	at [email protected]/org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152) ~[spring-test-6.1.11.jar:?]
    	... 130 more
 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionBeanPostProcessor' defined in URL [jar:file:///home/xeno/IdeaProjects/spring-app-commons/module/jpa/build/libs/jpa.jar!/com/xenoterracide/jpa/transaction/TransactionBeanPostProcessor.class]: class org.springframework.context.annotation.ConfigurationClassEnhancer$BeanFactoryAwareMethodInterceptor (in module spring.context) cannot access class com.xenoterracide.jpa.transaction.TransactionBeanPostProcessor$$SpringCGLIB$$0 (in module com.xenoterracide.jpa) because module com.xenoterracide.jpa does not export com.xenoterracide.jpa.transaction to module spring.context

    	at [email protected]/org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108) ~[spring-boot-test-3.3.2.jar:?]
    	at [email protected]/org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:225) ~[spring-test-6.1.11.jar:?]
    	at [email protected]/org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:152) ~[spring-test-6.1.11.jar:?]
    	... 130 more
    Caused by: java.lang.IllegalAccessException: class org.springframework.context.annotation.ConfigurationClassEnhancer$BeanFactoryAwareMethodInterceptor (in module spring.context) cannot access class com.xenoterracide.jpa.transaction.TransactionBeanPostProcessor$$SpringCGLIB$$0 (in module com.xenoterracide.jpa) because module com.xenoterracide.jpa does not export com.xenoterracide.jpa.transaction to module spring.context
    	at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:394) ~[?:?]

org.springframework:spring-core:6.1.11


------------------------------------------------------------
Gradle 8.9
------------------------------------------------------------

Build time:    2024-07-11 14:37:41 UTC
Revision:      d536ef36a19186ccc596d8817123e5445f30fef8

Kotlin:        1.9.23
Groovy:        3.0.21
Ant:           Apache Ant(TM) version 1.10.13 compiled on January 4 2023
Launcher JVM:  21.0.4 (Eclipse Adoptium 21.0.4+7-LTS)
Daemon JVM:    /home/xeno/.asdf/installs/java/temurin-21.0.4+7.0.LTS (no JDK specified, using current Java home)
OS:            Linux 6.6.41-1-MANJARO amd64

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: coreIssues in core modules (aop, beans, core, context, expression)status: duplicateA duplicate of another issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions