So I have this solution in my mind:
- Start simple in each starter library start defining one
@Configuration
class with a @ComponentScan(basePackages=“com.acme.libn)
when done release all the libriaries on the nexus (Note that this is a bad practice the starters should define the beans in the @Configuration
classes but for this step will be used as a workaround).
- Go on the consumers and remove
@ComponentScan
, update library and deploy. This will be the fastest way to remove the scanning of the beans on the main com.acme
package.
- Now you are free to work on each library as you prefer. Example: refactor the packages, declaring beans in the
@Configuration
, use @ConditionalOn…
, remove @ComponentScan
, use more @Configuration
classes (you have to link them in the spring.factories file), start using prefix for using propeties defined in the consumers …, you can work in parallel on this task with your team. And release one library when it’s ready if you don’t want to release all of them together.
- Re go in the consumers and refactor if needed, update the library that are ready and deploy. Go to step 3 till the libriaries are finished.
Otherwise you have to refactor com.acme
package in each library and in each consumers, keeping the @ComponentScan
in the consumers. When done with all the libriaries you can then remove it. You don’t have to do it all together, you can do it one library at time and one consumer at time.
PS: if you have entities and you are using spring-data in your libraries let me know I will update the answer because there is extra work to do.
I’ve read the documentation you have linked and I don’t know if it’s outdated or not. I’m using spring.factories file as for example stated here.I’m using spring boot 2.7.0. So check the correct configuration for the version of spring boot you are using
EDIT
I've read better the documentation and digged into the spring boot code META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.import
can be used to tell spring where the @Configuration\@AutoCOnfiguration
classes are. You can also use META-INF\spring.factories
to declare the @Configuration\@AutoConfiguration
classes. In the source code they are using the first option. Honestly I've not undersood the difference.
I think I've also discovered how to expose @RestController
or any other component in a starter without using @ComponentScan
as they say in the doc you must use @Import
example:
@Configuration
@Import({RestController.class, SomeService.class})
class ConfigurationClass {
}
@RestController
class RestController {
}
@Service
class SomeService {
}
This will make the SomeService
avaiable for injection, and I think this will expose automatically the endpoint defined in RestController
, like spring-boot-starter-actuator.
For the repositories of spring-data-jpa you have to use this in the ConfigurationClass
example:
@Configuration
@AutoConfigureAfter(JpaRepositoriesAutoConfiguration.class)
@EnableJpaRepositories(basePackages = "com.example")
@Import({Entity1.class, Entity2.class})
class ConfigurationClass {
}
@Entity
public class Entity1 {
}
@Entity
public class Entity2 {
}
In this way the repositories interfaces present in com.example
will be ready for injection in the configuration class or outside the jar. In my project I was able to load entities only using @EntityScan
in the consumer of the starter I have to make a try with @Import.
All the things that I've writed in the EDIT section must be tested, the only exception is the configuration for jpa repositories with @EntityScan
on the consumer. I've had no time for test right now.
So in the end you can remove then @ComponentScan
in the first step I've writed and use @Import
, but you have to list all the classes that are annotated like @Component\@Service...
. In this way you don't have to declare and construct all the beans of the step 3 in the configuration classes.
EDIT 2 I've made some test you will find the code here
what i discovered:
- Adding the configuration classes in
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.import
doesn't work, you have to use META-INF\spring.factories
if you check the code I've commented the configuration class in the file
@Import
with entities doesn't work, unlikly you have to put @EntityScan
in the cosnumer declaring all packages where the entities are.
For the rest everithing is fine. You can play with it:
POST localhost:8080/someEntities
request body
{
"name" : "entity1"
}
response
{
"id": 1,
"name": "entity1"
}
{
"id": 1,
"name": "entity1"
}
GET localhost:8080/someEntities/1
{
"id": 1,
"name": "entity1"
}
EDIT 3 from spring boot v2.7 the classes annotated with @AutoConfiguration
are migrated to a new file META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
(nothe the final s so imports) see this question for more info. The configuration classes declared in spring.factories
will still be honored