Spring: Autoconfiguration package and the missing JPA Entities (Not a managed type error)

Updated:

Why you get one of these errors even if you declared correctly your @Entity?

org.springframework.beans.factory.UnsatisfiedDependencyException: 

or

Caused by: java.lang.IllegalArgumentException: Not an managed type: class 

Adding JPA Entities in a separate module from @SpringApplication

In our project we have a Maven module that contains a Spring JPA repository and multiple JPA Entities representing tables in the database that are optional in the project and are considered plug-ins.

One of the issue we encountered is the integration of these classes in the main project.

@SpringApplication and autoconfiguration

SpringApplication imports @Components included in his directory (package) and sub-directories (sub-packages), for this reason we need to tell to @SpringApplication to look in other packages.

Adding @AutoConfigurationPackage in the @Configurationclass of the plugin module allow us to automatically declare (almost) all the Components of the plugin module without the need to explicitly import the components of the plug-in module in the main module.

@Entity and @EntityScan will break the configuration of your code

The issue is when you have an @Entity in your plug-in module. Spring cannot automatically import Entities from the module using @AutoConfigurationPackage and requires that you use @EntityScan to scan the entities.

Unfortunately, using @EntityScan will break the auto configuration of Spring in the main module (the one with @SpringApplication).

This behaviour is explicitly stated in GitHub by the Spring developers.

We should update @EntityScan at the same time to make it clear that using it will result in @AutoConfigurationPackage being ignored.

and

I would expect it to update the reference documentation and the javadoc for both @EntityScan and @AutoConfigurationPackage to make the purpose of the two more clear and to highlight that auto-configuration packages are the default packages used for entity scanning, with @EntityScan being used to take complete control and override those defaults.

This means that adding @EntityScan will tell to @SpringApplication that you want to manage directly the entity scanning and de-activate the automatic scanning. Doing this you will have to add manually in @EntityScan not only the packages of the plug-in module but the packages of the main module, because Spring Boot won't look for these.

Without this change you will get, surprisingly, the error:

org.hibernate.MappingException: Unknown entity 

Interestingly, @EnableJpaRepositories is not required because included in @AutoConfigurationPackage.

AutoConfigurationPackage

@AutoConfigurationPackage is a Spring annotation used to automatically register a package for component scanning. This annotation is typically used in the main application class, and it serves as a hint to Spring about which packages to scan for components (such as @Component, @Service, @Repository, etc.) and automatically configure them.

When you use Spring Boot, it automatically detects and registers beans by scanning the classpath for components. However, it needs to know where to start scanning from. The @SpringBootApplication annotation, which is a composite annotation that includes @EnableAutoConfiguration, already registers a default package to scan for components, which is the package of the main class where it is declared.

But if your components are located in a different package or if you have multiple packages containing components, you can use the @AutoConfigurationPackage annotation to add additional packages to the component scan.

Here's an example of how you can use @AutoConfigurationPackage annotation in a Spring Boot application:

@SpringBootApplication 
@AutoConfigurationPackage 
public class MyApplication { 
    public static void main(String[] args) { 
        SpringApplication.run(MyApplication.class, args); 
    } 
} 

In the above example, @AutoConfigurationPackage annotation is used to register the package of MyApplication class for component scanning, which means Spring Boot will scan and configure all the components in this package and its sub-packages. If you have components in other packages, you can add them as additional arguments to the annotation:

@SpringBootApplication 
@AutoConfigurationPackage(basePackages = {"com.example.package1", "com.example.package2"}) 
public class MyApplication { 
    public static void main(String[] args) { 
        SpringApplication.run(MyApplication.class, args); 
    } 
} 

In this example, @AutoConfigurationPackage is used to register two additional packages, com.example.package1 and com.example.package2, for component scanning.


You could be interested in

logo of the category: spring-big.svg Spring Boot: REST controller Test example

How to test the @RestController with Spring Boot
2017-10-01

logo of the category: spring-big.svg How to deploy a Java and Angular webapp in one JAR/WAR

How to configure a fullstack Angular and Spring Boot application
2018-04-26
WebApp built by Marco using SpringBoot 3.2.4 and Java 21, in a Server in Switzerland