Search code examples
springspring-transactions

Can I programmatically add a qualifier to a bean?


I am registering transaction managers in my code, I would normally use annotation based configuration but as I don't know until runtime how many data sources (and hence transaction managers) there will be, I have to programmatically register these, as follows:

private final void registerTransactionManagerBean(final DataSource dataSource, ConfigurableApplicationContext context) {

    String transactionManagerName = this.getName() + "-transactionManager";

    context.getBeanFactory().registerSingleton(transactionManagerName, new DataSourceTransactionManager(dataSource));

    LOG.info("Registering transaction manager under name : " + transactionManagerName);
}

Assuming this.getName() returned 'mydb', I originally expected to be able to qualify a transaction manager like this:

@Transactional("mydb-transactionManager")

What I've realised however is the value of that annotation refers to the qualifier and not the name. I did a quick test by declaring a bean as below and it works:

@Bean
@Qualifier("mydb-transactionManager")
public PlatformTransactionManager test() {
    return new DataSourceTransactionManager(new EmbeddedDatabaseBuilder().build());
}

My question is, is there a way I can programmatically add a qualifier when registering a bean?

UPDATE

I've worked this out, I'm falling foul of this problem (in BeanFactoryAnnotationUtils:isQualifierMatch):

catch (NoSuchBeanDefinitionException ex) {
// ignore - can't compare qualifiers for a manually registered singleton object
}

I am manually registering my transaction manager bean so I presume this is why I'm stuck. I'm not really sure what options that gives me apart from to not programmatically register transaction managers as a runtime thing sadly.


Solution

  • I've worked this out, I'm falling foul of this problem:

    catch (NoSuchBeanDefinitionException ex) {
    // ignore - can't compare qualifiers for a manually registered singleton object
    }
    

    I am manually registering my transaction manager bean so I presume this is why I'm stuck. I'm not really sure what options that gives me apart from to not programatically register transaction managers as a runtime thing sadly.

    Raised as a JIRA issue - https://jira.spring.io/browse/SPR-11915