Spring: Autoconfiguration package and the missing JPA Entities (Not a managed type error)
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 @Configuration
class 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.
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.