2

I am looking to override the SSLContext of Spring at runtime. Hence I am trying to find ways to register the below method as a bean dynamically.

For Ex. When a GetMapping endpoint is invoked, the below method should be injected as a bean into Spring IoC.

public static SSLContext getSSLContext() throws Exception {
    TrustManager[] trustManagers = new TrustManager[] {
            new ReloadableX509TrustManager(truststoreNewPath)
    };
    SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, trustManagers, null);
    return sslContext;
}

How can I do this?

Sapnesh Naik
  • 9,671
  • 6
  • 52
  • 82
  • something like this https://stackoverflow.com/questions/4540713/add-bean-programmatically-to-spring-web-app-context – Deadpool Jul 23 '19 at 06:19

4 Answers4

1

You can use the ConfigurableBeanFactory to register beans manually at runtime.

@Service
public class RegisterBeansDynamically implements BeanFactoryAware {

    private ConfigurableBeanFactory beanFactory;

    public <T> void registerBean(String beanName, T bean) {
        beanFactory.registerSingleton(beanName, bean);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = (ConfigurableBeanFactory) beanFactory;
    }
}

But keep in mind: Your context must be refreshed making other beans able getting your new bean automatically injected or they have to access them dynamically from the application context.

The BeanFactory can also be accessed directly through the application context see this answer.

vvursT
  • 432
  • 5
  • 12
1

Spring 5 provides Bean registration, which can be done dynamically. Please look at documentation here and example here.

Supplier<SSLContext> sslcontextSupplier = () -> getSSLContext();
context.registerBean("sslcontext",SSLContext.class,sslcontextSupplier);
Bharat
  • 186
  • 3
  • 19
0

you should annotate the method with @bean and class with @configuration see docs https://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch02s02.html

@Bean 
public static SSLContext getSSLContext() throws Exception {
TrustManager[] trustManagers = new TrustManager[] {
        new ReloadableX509TrustManager(truststoreNewPath)
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagers, null);
return sslContext;
}
Manoj Krishna
  • 674
  • 4
  • 15
  • I am aware of it. But that is not by intent. I want to register the bean dynamically whenever I want to, using @bean will load it on App start – Sapnesh Naik Jul 23 '19 at 06:22
0

Here is the demo.

public class Demo implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        ConfigurableApplicationContext context = (ConfigurableApplicationContext)applicationContext;
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)context.getBeanFactory();

        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(YourClass.class);

        beanDefinitionBuilder.addPropertyValue("property1", "propertyValue");
        beanDefinitionBuilder.addPropertyValue("property2", applicationContext.getBean(AnotherClass.class));


        beanFactory.registerBeanDefinition("yourBeanName", beanDefinitionBuilder.getBeanDefinition());


    }
}

You can move the register part to your method(start from BeanDefinitionBuilder). I suppose this will suit your demand.

weaver
  • 1,081
  • 2
  • 9
  • 23