rj93
rj93

Reputation: 573

Spring boot autoconfiguration from a generated source

I'm in the process of creating a custom openapi-generator, to auto generate configuration properties and (hopefully) AutoConfiguration.

I have it generating everything into target/generated-sources/demo-client.

It generates the following structure:

└── src
    └── main
        ├── AndroidManifest.xml
        ├── java
        │   └── com
        │       └── demo
        │           └── custom
        │               ├── ApiClient.java
        │               ├── ...
        │               ├── api
        │               │   ├── PetApi.java
        │               │   ├── StoreApi.java
        │               │   └── UserApi.java
        │               ├── config
        │               │   ├── DemoApiClientAutoConfiguration.java
        │               │   └── DemoApiProperties.java
        │               └── model
        │                   ├── Address.java
        │                   └── ...
        └── resources
            └── META-INF
                ├── spring
                │   └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
                └── spring.factories

And the classes are as follows:

DemoApiProperties.java:

@Component
@ConfigurationProperties("m2m.demo")
public class DemoApiProperties {

    private String baseUrl = "demo-service";

    public String getBaseUrl() {
        return baseUrl;
    }

    public void setBaseUrl(String baseUrl) {
        this.baseUrl = baseUrl;
    }

}

DemoApiClientAutoConfiguration.java:

@AutoConfiguration
@ConditionalOnProperty("m2m.demo.base-url")
public class DemoApiClientAutoConfiguration {

    @Bean
    public ApiClient demoM2mApiClient(RestClient m2mRestClient, DemoPackageApiProperties apiProperties) {
        ApiClient apiClient = new ApiClient(demoM2mApiClient);
        apiClient.setBasePath(apiProperties.getBaseUrl());
        return apiClient;
    }

    @Bean
    public PetApi petApi(ApiClient demoM2mApiClient) {
        return new PetApi(demoM2mApiClient);
    }

    @Bean
    public StoreApi storeApi(ApiClient demoM2mApiClient) {
        return new StoreApi(demoM2mApiClient);
    }

    @Bean
    public UserApi userApi(ApiClient demoM2mApiClient) {
        return new UserApi(demoM2mApiClient);
    }


}

And then the META-INF files:

org.springframework.boot.autoconfigure.AutoConfiguration.imports

com.demo.custom.config.DemoApiClientAutoConfiguration

And as you can see I've even tried in the spring boot two way, using spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.demo.custom.config.DemoApiClientAutoConfiguration

But whenever I start the application it is not finding the DemoApiClientAutoConfiguration so it isn't processing it, from looking at the debug logs Spring Boot isn't discovering that this AutoConfiguration exists.

If I update my application to use Imports it works fine:

// this is exactly the same class as whats in the AutoConfiguration imports
import com.demo.custom.config.DemoApiClientAutoConfiguration; 

@SpringBootApplication
@Import({
  DemoApiClientAutoConfiguration.class
})
public class MyServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(FeeEngineApplication.class, args);
    }

}

I am using Spring Boot 3.4.0.

Is it possible for Spring to pickup generated-sources AutoConfiguration's? It's not the end of the world if we have to use @Import, would just be nice to remove that extra verbosity.

Upvotes: 0

Views: 81

Answers (1)

Hamza Naceur
Hamza Naceur

Reputation: 36

I think you are missing the EnableConfigurationProperties Annotation on the Autoconfiguration class.

It should be:

@AutoConfiguration
@ConditionalOnProperty("m2m.demo.base-url")
@EnableConfigurationProperties(DemoApiProperties.class)
public class DemoApiClientAutoConfiguration {

    @Bean
    public ApiClient demoM2mApiClient(RestClient m2mRestClient, DemoPackageApiProperties apiProperties) {
        ApiClient apiClient = new ApiClient(demoM2mApiClient);
        apiClient.setBasePath(apiProperties.getBaseUrl());
        return apiClient;
    }

    @Bean
    public PetApi petApi(ApiClient demoM2mApiClient) {
        return new PetApi(demoM2mApiClient);
    }

    @Bean
    public StoreApi storeApi(ApiClient demoM2mApiClient) {
        return new StoreApi(demoM2mApiClient);
    }

    @Bean
    public UserApi userApi(ApiClient demoM2mApiClient) {
        return new UserApi(demoM2mApiClient);
    }

Be sure to have the property m2m.demo.base-url in your configuration file in order for this to work, i would also recommend to change that and add a boolean property to enable/disable the configuration and use it instead of the url.


Spring boot 3.x autoconfiguration doc

https://docs.spring.io/spring-boot/reference/features/developing-auto-configuration.html#features.developing-auto-configuration

in short: don't use META-INF/spring.factories but META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

Upvotes: 0

Related Questions