Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@AutoConfigureBefore does not trigger

Tags:

spring-boot

The intention of this project is to create hooks into Spring Boot's lifecycle, right before Liquibase executes its database schema changesets. The hooks will eventually be used to start / stop a Docker (or Docker-like) container with a Postgres instance. The project must be able to deal with:

  • tests run from the IDE (IntellIJ, STS)
  • tests run with Maven Surefire
  • spring-boot:run
  • executable JAR
  • integration test on CI server

Given the above limitations, the best approach appeared to be to have an Auto-Configuration and instructing it to run before Liquibase.

The Auto-Configuration class has been annotated:

@ConditionalOnProperty(prefix = "docker_42", 
    name = "enabled", matchIfMissing = false)
@AutoConfigureBefore({LiquibaseAutoConfiguration.class })
public class Docker42AutoConfiguration {

spring.factories has a single entry:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
nl._42.autoconfig.Docker42AutoConfiguration

The entire (stripped down) project can be found here: https://github.com/robert-bor/auto-configuration-question

The results can be verified by either:

  • setting up the project in your IDE & running a test, or
  • executing spring-boot:run

In Spring Boot's log you will see Liquibase executing before the custom AutoConfiguration.

Note that various other routes have been tried (ApplicationListener, RunListener), but none played nice with all the required in-roads.

Pointers as to why @AutoConfigureBefore does not work in my project would be very much appreciated.

like image 987
robert_bor Avatar asked Nov 21 '16 19:11

robert_bor


People also ask

What is the difference between @configuration and autoconfiguration?

You can use @EnableAutoConfiguration annotation along with @Configuration annotation. It has two optional elements, exclude : if you want to exclude the auto-configuration of a class. excludeName : if you want to exclude the auto-configuration of a class using fully qualified name of class.

How do you create an autoconfiguration?

In order to create a custom auto-configuration, we need to create a class annotated as @Configuration and register it. Let's create a custom configuration for a MySQL data source: @Configuration public class MySQLAutoconfiguration { //... } Next, we need to register the class as an auto-configuration candidate.

Can we have conditional based presence or absence of specific bean in spring boot?

36.3.The @ConditionalOnBean and @ConditionalOnMissingBean annotations allow configurations to be skipped based on the presence or absence of specific beans. You can use the value attribute to specify beans by type, or name to specify beans by name.

Where is Meta INF spring factories?

factories and place it in src/main/resources/META-INF . In spring. factories , set org. springframework.


1 Answers

You're trying to apply a configuration semantic to some runtime constraints. Auto-configuration is about providing bean definitions in the context, something that will ultimately create bean instances that you can wire in your components.

Assume that you need bean Foo in order to auto-configure something. You need to make sure that FooAutoConfiguration runs before yours so that the context has a chance to contain a bean definition for Foo. That is explained in quite details in our last Devoxx university.

The documentation you referenced in that comment does not imply runtime constraints in any way:

Hint for that an auto-configuration should be applied before other specified auto-configuration classes.

applying the auto-configuration does not mean that the beans created by that configuration will effectively start before the beans created by another configuration. In other words, what you've done is making sure that your auto-configuration configures the context before the liquibase auto-configuration has a chance to do so. It does not imply, in any way, that the beans that will be created (we're not there yet) will be created in that order.

If that's what you want to do and you have no bean dependency, you can just forget about all that and create a bean lifecycle dependency instead. It can be tricky because liquibase may or may not be there but we essentially do that for Hazelcast (see the auto-configuration). Basically we need to make sure that Hazelcast is started before the JPA container is started in case it wants to use Hazelcast as second level cache.

like image 102
Stephane Nicoll Avatar answered Sep 28 '22 05:09

Stephane Nicoll