1

I wanna use the properties to set some swagger docket to spring but I cant get the properties when I implements ImportBeanDefinitionRegistrar and get an error

Caused by: java.lang.NoSuchMethodException: com.github.sofior.swagger.SwaggerAutoConfiguration.<init>()

@Configuration
@EnableSwagger2
@EnableConfigurationProperties(SwaggerProperties.class)
public class SwaggerAutoConfiguration implements ImportBeanDefinitionRegistrar {

    private final SwaggerProperties properties;

    public SwaggerAutoConfiguration(SwaggerProperties properties) {
        this.properties = properties;
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        System.out.println(properties);
        properties.getDockets().forEach((docketName, docketProperties) -> {
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Docket.class);
            builder.addConstructorArgValue(docketProperties.getType());
            builder.addConstructorArgValue(docketProperties.getType());
            registry.registerBeanDefinition(docketName, builder.getRawBeanDefinition());
        });
    }

}
谢林志
  • 71
  • 1
  • 8

4 Answers4

2

I think it is impossible to do this, because spring have two phase

1.bean registration

2.bean initialization and instantiation

SwaggerProperties can only be used after phase 2 when it is finished to instantiate, but registerBeanDefinitions is the phase 1

clevertension
  • 6,929
  • 3
  • 28
  • 33
0

Basically you need to inject the properties to your class constructor. So the configurations should be Autowired in order to work them.

@Autowired
public SwaggerAutoConfiguration(SwaggerProperties properties) {
    this.properties = properties;
}

This should fix your "properties" is null issue.

Damith
  • 740
  • 4
  • 12
0

the workaround of this question is to read a new properties during registerBeanDefinitions

EnableCustomSwagger

import org.springframework.context.annotation.Import;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(SwaggerAutoConfiguration.class)
public @interface EnableCustomSwagger {
    String path() default "";
}

SwaggerAutoConfiguration

import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;


public class SwaggerAutoConfiguration implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        String clsName = EnableCustomSwagger.class.getName();
        AnnotationAttributes attrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(clsName, false));
        if (!attrs.getString("path").equals("")) {
            String path = attrs.getString("path");
            ResourceLoader loader = new DefaultResourceLoader();
            Resource resource = loader.getResource(path);
            // you can get the value from your property files
        }

        //how can I get properties here,the properties is null

//        properties.getDockets().forEach((docketName, docketProperties) -> {
//            BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Docket.class);
//            builder.addConstructorArgValue(docketProperties.getType());
//            builder.addConstructorArgValue(docketProperties.getType());
//            registry.registerBeanDefinition(docketName, builder.getRawBeanDefinition());
//        });
    }

}

Application

@SpringBootApplication
@EnableCustomSwagger(path="classpath:docklet.properties")
public class Application {
}
clevertension
  • 6,929
  • 3
  • 28
  • 33
  • Did you ever get this working? Properties will still be null. I'd like to do the same thing, have bean settings in properties file and then, dynamically, create and register those beans. – Dimitar Vukman Aug 12 '19 at 15:14
0

spring 2.x

import org.springframework.boot.context.properties.bind.Binder;
public class MultipleDataSourceComponentRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {
...

private Environment environment; @Override public void setEnvironment(Environment environment) { this.environment = environment; }

 @Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    ConfigurationProperties annotationCp = MultipleDataSourceSetProperties.class.getAnnotation(ConfigurationProperties.class);
    MultipleDataSourceSetProperties properties = Binder.get(environment).bind(annotationCp.prefix(), MultipleDataSourceSetProperties.class).get();

}

...

nixinhua
  • 31
  • 1