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

Use of @EntityScan causes AOT instance supplier code generation error #34371

Closed
trcoelho opened this issue Feb 24, 2023 · 12 comments
Closed

Use of @EntityScan causes AOT instance supplier code generation error #34371

trcoelho opened this issue Feb 24, 2023 · 12 comments
Labels
type: regression A regression from a previous release
Milestone

Comments

@trcoelho
Copy link

Hello!

After updating to Spring boot 3.0.3, native images are showing up the following exception:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.0.3)

2023-02-24T10:15:53.005-03:00  INFO 4316 --- [           main] c.example.application.ApplicationConfig  : Starting ApplicationConfig using Java 17.0.6 with PID 4316 (C:\Users\tcoelho1\Desktop\spring-boot-3.0.3\target\classes started by tcoelho1 in C:\Users\tcoelho1\Desktop\spring-boot-3.0.3)
2023-02-24T10:15:53.012-03:00  INFO 4316 --- [           main] c.example.application.ApplicationConfig  : No active profile set, falling back to 1 default profile: "default"
2023-02-24T10:15:54.469-03:00  INFO 4316 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2023-02-24T10:15:54.620-03:00  INFO 4316 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 127 ms. Found 1 JPA repository interfaces.
Exception in thread "main" java.lang.IllegalArgumentException: Code generation is not supported for bean definitions declaring an instance supplier callback : Root bean: class [org.springframework.boot.autoconfigure.domain.EntityScanPackages]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null
        at org.springframework.beans.factory.aot.BeanDefinitionMethodGenerator.<init>(BeanDefinitionMethodGenerator.java:82)
        at org.springframework.beans.factory.aot.BeanDefinitionMethodGeneratorFactory.getBeanDefinitionMethodGenerator(BeanDefinitionMethodGeneratorFactory.java:100)
        at org.springframework.beans.factory.aot.BeanDefinitionMethodGeneratorFactory.getBeanDefinitionMethodGenerator(BeanDefinitionMethodGeneratorFactory.java:115)
        at org.springframework.beans.factory.aot.BeanRegistrationsAotProcessor.processAheadOfTime(BeanRegistrationsAotProcessor.java:48)
        at org.springframework.beans.factory.aot.BeanRegistrationsAotProcessor.processAheadOfTime(BeanRegistrationsAotProcessor.java:36)
        at org.springframework.context.aot.BeanFactoryInitializationAotContributions.getContributions(BeanFactoryInitializationAotContributions.java:67)
        at org.springframework.context.aot.BeanFactoryInitializationAotContributions.<init>(BeanFactoryInitializationAotContributions.java:49)
        at org.springframework.context.aot.BeanFactoryInitializationAotContributions.<init>(BeanFactoryInitializationAotContributions.java:44)
        at org.springframework.context.aot.ApplicationContextAotGenerator.lambda$processAheadOfTime$0(ApplicationContextAotGenerator.java:58)
        at org.springframework.context.aot.ApplicationContextAotGenerator.withCglibClassHandler(ApplicationContextAotGenerator.java:67)
        at org.springframework.context.aot.ApplicationContextAotGenerator.processAheadOfTime(ApplicationContextAotGenerator.java:53)
        at org.springframework.context.aot.ContextAotProcessor.performAotProcessing(ContextAotProcessor.java:106)
        at org.springframework.context.aot.ContextAotProcessor.doProcess(ContextAotProcessor.java:84)
        at org.springframework.context.aot.ContextAotProcessor.doProcess(ContextAotProcessor.java:49)
        at org.springframework.context.aot.AbstractAotProcessor.process(AbstractAotProcessor.java:82)
        at org.springframework.boot.SpringApplicationAotProcessor.main(SpringApplicationAotProcessor.java:80)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  15.942 s
[INFO] Finished at: 2023-02-24T10:15:57-03:00
[INFO] ------------------------------------------------------------------------

When run mvn -Pnative spring-boot:build-image.

Curiously it did not happen on Spring boot 3.0.2.

I've attached these two projects that happens what I explained.

spring-boot-examples.zip

Am I missing some configuration or is this a bug?

Thanks in advance.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Feb 24, 2023
@scottfrederick
Copy link
Contributor

This is an intentional change in Spring Framework 6.0.5, which is used in Spring Boot 3.0.3. See spring-projects/spring-framework#29556 for the details and spring-projects/spring-framework#29555 for discussion on potential future changes in Framework.

@scottfrederick scottfrederick closed this as not planned Won't fix, can't repro, duplicate, stale Feb 24, 2023
@scottfrederick scottfrederick added for: external-project For an external project and not something we can fix and removed status: waiting-for-triage An issue we've not yet triaged labels Feb 24, 2023
@trcoelho
Copy link
Author

Hi @scottfrederick , thanks for quickly reply.

So that means we are unable to build native images when application uses Spring Data on 3.0.3?

Do you know if It will be "fixed" in future Spring boot/Spring releases?

Thank you.

@wilkinsona
Copy link
Member

I wonder if we've missed replacing this code:

@Override
public Supplier<?> getInstanceSupplier() {
return () -> new EntityScanPackages(StringUtils.toStringArray(this.packageNames));
}

That said, our JPA smoke test is passing at the moment. Perhaps the use of custom packages in the sample is the cause?

@scottfrederick
Copy link
Contributor

Thanks for the sample @trcoelho, I should have looked more closely at it before closing the issue. The presence of the @EntityScan annotation triggers this error. This wasn't caught by the JPA smoke test that Andy mentioned, which we use to verify AOT behavior across Spring projects.

@scottfrederick scottfrederick changed the title Spring boot 3.0.3 - Code generation is not supported for bean definitions declaring an instance supplier callback : Root bean: class [org.springframework.boot.autoconfigure.domain.EntityScanPackages] Use of @EntityScan causes AOT instance supplier code generation error Feb 24, 2023
@scottfrederick scottfrederick added type: regression A regression from a previous release and removed for: external-project For an external project and not something we can fix labels Feb 24, 2023
@scottfrederick scottfrederick added this to the 3.0.x milestone Feb 24, 2023
@wilkinsona
Copy link
Member

Thinking about this some more, I don't think @EntityScan actually does anything in a native image.

In Spring Framework 6.0.4, custom instance suppliers were silently ignored. This means that in Boot 3.0.2, the entity scan packages are empty. That doesn't actually matter because the persistent types have been found at build time and recorded in the PersistenceManagedTypes bean definition:

    /**
     * Get the bean instance for 'persistenceManagedTypes'.
     */
    private static PersistenceManagedTypes getPersistenceManagedTypesInstance() {
      List<String> managedClassNames = List.of("com.example.entity.Authentication", "com.example.entity.IdentifiableEntity");
      List<String> managedPackages = List.of();
      return PersistenceManagedTypes.of(managedClassNames, managedPackages);
    }

    /**
     * Get the bean definition for 'persistenceManagedTypes'
     */
    public static BeanDefinition getPersistenceManagedTypesBeanDefinition() {
      Class<?> beanType = PersistenceManagedTypes.class;
      RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
      beanDefinition.setPrimary(true);
      beanDefinition.setInstanceSupplier(PersistenceManagedTypesConfiguration__BeanDefinitions::getPersistenceManagedTypesInstance);
      return beanDefinition;
    }

The change in Framework 6.0.5 means that the instance supplier is no longer ignored and causes a failure instead. I think we can just exclude the bean during AOT processing.

@wilkinsona
Copy link
Member

@trcoelho You can work around the problem with Spring Boot 3.0.3 by using a BeanRegistrationExcludeFilter:

package com.example;

import org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter;
import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.boot.autoconfigure.domain.EntityScanPackages;

class EntityScanExcludeFilter implements BeanRegistrationExcludeFilter {

	@Override
	public boolean isExcludedFromAotProcessing(RegisteredBean registeredBean) {
		return registeredBean.getBeanClass().equals(EntityScanPackages.class);
	}

}

Such filters are registered in a file named META-INF/spring/aot.factories under the key org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter:

org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter=\
com.example.EntityScanExcludeFilter

@trcoelho
Copy link
Author

Thanks @wilkinsona !

Is this will be fixed on next spring boot release?

Thank you.

@wilkinsona
Copy link
Member

We hope so, yes.

@trcoelho
Copy link
Author

trcoelho commented Mar 4, 2023

Hi all.

FYI

Have tested on Spring Boot 3.0.4 and we still got same issue. :(

Thank you.

@scottfrederick
Copy link
Contributor

@trcoelho The issue is still open, indicating that we haven't attempted to fix this problem yet. When we have a fix the issue will be closed and assigned to a specific version milestone.

@CasaSky
Copy link

CasaSky commented Jun 3, 2023

fyi: The issue is still occuring while running tests with @SpringBootTest using latest spring boot version "3.1.0"

@philwebb
Copy link
Member

philwebb commented Jun 3, 2023

@CasaSky Are you able to open a new issue and provide a reproducer?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

6 participants