Spring @Transactional in @Bean declaration instead of class Implementation

I would like to set up "transactional" beans from my Spring class @Configuration

instead of annotating the class implementation itself with @Transactional

.

Kind of like the old school way, setting up transactional tips from an XML file, but no String reference to my class / method names for creating pointcuts.

The reason is that the bean implementation is in a different code base and the module it belongs to is independent of Spring. Read: I am not touching the source code of this bean, just creating it. The class is final, it cannot extend it either to add Spring annotations to the child class. Let's say that all methods should be transactional for simplicity.

Bean implementation:

/** This class has no Spring dependency... */
// @Transactional <- which means I can't use this here
public final class ComplexComponentImpl implements ComplexComponent {

    private SomeRepository repo;

    public ComplexComponentImpl(SomeRepository repository) { this.repo = repository }

    public void saveEntities(SomeEntity e1, SomeEntity e2) {
        repo.save(e1);
        throw new IllegalStateException("Make the transaction fail");
    }

      

What I want to do in my config class (and that doesn't work in my unit test):

@Configuration
@EnableTransactionManagement
public class ComplexComponentConfig {

    @Bean
    @Transactional // <- Make the bean transactional here
    public ComplexComponent complexComponent() {
        return new ComplexComponentImpl(repository());
    }

    // ...
}

      

The above example doesn't work, as nothing gets the transaction at runtime: the object is e1

retained even if an exception is thrown.

Please note that my transaction management setup works fine with the implementation class marked @Transactional

.

Question : Is it possible to declare a transaction @Bean

from a class @Configuration

, or is there any alternative taking into account the restrictions above?

+3


source to share


3 answers


Found something built in, this is the sum of @Mecon and @Erik Gillespie , with a limited template.

Spring already provides TransactionProxyFactoryBean

which just sets up a transactional proxy for any entity. Most of the settings can be refactored to some utility method:



@Configuration
@EnableTransactionManagement
public class ComplexComponentConfig {

    /** NOT A @Bean, this object will be wrapped with a transactional proxy */
    public ComplexComponent complexComponentImpl() {
        return new ComplexComponentImpl(repository());
    }

    @Bean
    public ComplexComponent complexComponent() {
        TransactionProxyFactoryBean proxy = new TransactionProxyFactoryBean();

        // Inject transaction manager here
        proxy.setTransactionManager(txManager());

        // Define wich object instance is to be proxied (your bean)
        proxy.setTarget(complexComponentImpl());

        // Programmatically setup transaction attributes
        Properties transactionAttributes = new Properties();
        transactionAttributes.put("*", "PROPAGATION_REQUIRED");
        proxy.setTransactionAttributes(transactionAttributes);

        // Finish FactoryBean setup
        proxy.afterPropertiesSet();
        return (ComplexComponent) proxy.getObject;
    }

// ...
}

      

+4


source


I think you probably cannot use @Transactional this way. One of spring's built-in PostProcessors should scan all classes (beans) that have this annotation and create Aspects accordingly.



On the alternatives: I would write an adapter class for every third class I have to use. And then make these spring Beans adapter classes.

+1


source


You cannot use @Transactional

this way, but you can programmatically configure aspects with Spring.

Spring documentation for programmatically defining aspects:

The examples in the documentation are very simple. Defining aspects of transactions is likely to be more complex, and I wouldn't be surprised if you find it easier to just use the convenience of XML-based proxies or take @ Mecon's advice and write adapters.

+1


source







All Articles