0

I want to connect different databases based on User login, So I am having the TransactionManager bean as Prototype scope and it is creating transacionManager bean everytime, and works well. But , Is it good when the scope of the application increases and how stable it will be?

Any ideas ? Thanks.

@Bean(initMethod = "init", destroyMethod = "destroy")
@Scope(value = "prototype")
public PlatformTransactionManager transactionManager() {

1 Answers1

0

Using it as prototype is a not a good practice. This actually means that each time transactionManager() is called, a new TransactionManager is created, which is redundant resource consuming, as a single instance for each TransactionManager configuration is enough.

Instead, create some factory bean, you can call it TransactionManagerFactory, which exposes a getter such as PlatformTransactionManager getUserTxManager(SomeRelevantUserDetails). This factory will create the various PlatformTransactionManagers for the various DB vendors only once each and return it to the caller according to SomeRelevantUserDetails.

TransactionManagerFactory class:

@Component
public class TransactionManagerFactory {

    private final PlatformTransactionManager mySqlTxManager;
    private final PlatformTransactionManager db2TxManager;
    private final PlatformTransactionManager hsqlTxManager;

    @Autowired
    protected TransactionManagerFactory(
        @Qualifier("mySqlTxManager") PlatformTransactionManager mySqlTxManager
        @Qualifier("db2TxManager") PlatformTransactionManager db2TxManager
        @Qualifier("hsqlTxManager") PlatformTransactionManager hsqlTxManager) {

        this.mySqlTxManager = mySqlTxManager;
        this.db2TxManager = db2TxManager;
        this.hsqlTxManager = hsqlTxManager;
    }

    public PlatformTransactionManager getUserTxManager(SomeRelevantUserDetails userDetails) {
        PlatformTransactionManager userTxManager = // put here logic to determine
        return userTxManager;
    }
}

Other service that requires a user-dependent transaction manager:

@Component
public class UsesTxManagerFactory {

    private final TransactionManagerFactory txManagerFactory;

    @Autowired
    protected UsesTxManagerFactory(TransactionManagerFactory txManagerFactory) {
        this.txManagerFactory = txManagerFactory;
    }

    public void someMethod() {
        SomeRelevantUserDetails userDetails = // create the relevant details
        PlatformTransactionManager txManager = getUserTxManager(userDetails);
        // perform transaction
    }
}
yair
  • 8,945
  • 4
  • 31
  • 50
  • Thank you very much for the response. Will try in this waya nd let you know. But in my case , I dont know how many transaction manager needs to be created, it is dynamic , it is upto the user accessing the application. – Mohamed Niyas Jan 03 '14 at 09:11
  • when using prototype, even the same user with the same required transaction manager properties, will cause creating a new one every time `PlatformTransactionManager transactionManager()` is called. – yair Jan 04 '14 at 21:09
  • If by "dynamic" you mean that it is configurable by the customer via some pre-startup configuration, then `TransactionManagerFactory` should load that configuration during initialization and create them all. If by "dynamic" you mean totally dynamic - even after initialization the user can request a new tx manager - then you *can* use `prototype` bean that can create new tx managers, only it should be wrapped by `TransactionManagerFactory` that should be gained with relevant knowledge to determine when should a new manager be created and when an existing one may be returned to the client. – yair Jan 04 '14 at 21:10
  • I am looking for a solution, which we will have single instance of an application and connected to multiple databases, one database per customer, a customer may have multiple users. So in my application i need to create a transaction manager per customer so all the users belongs to the customer will use same transaction manager, if another customer's user logs in then need to create a new transaction manager with respective datasource details. Customers database information will be stored in a main database, So everytime user logs in it will verify again the main database. – Mohamed Niyas Jan 05 '14 at 04:57
  • So it will be very helpful if someone came across this kind of solution. As I looked over for couple of days , there are solution only for switching databases, but I need to have connected to multiple databases concurrently. – Mohamed Niyas Jan 05 '14 at 05:02
  • How many customers do you have? Is it a fixed number or rather it may change during up-time of your application? – yair Jan 05 '14 at 09:57
  • No it is not fixed.. My application will be up all the time ... and while registering a new customer we will create a new database for the Customer.. So from the time on .. if that customer logs in he needs to be connected to that database.. any no of customers can connect at a time... – Mohamed Niyas Jan 05 '14 at 14:12