angryip
angryip

Reputation: 2290

how to inject specific datasource in grails 3

I am trying to follow the guide outlined in this URI: https://grails.github.io/grails-doc/latest/guide/single.html#multipleDatasources

My application.yml file, contains the following description for datasources:

dataSources:
    dataSource:
        pooled: true
        jmxExport: true
        driverClassName: org.h2.Driver
        username: sa
        password:
    raw:
        dialect: org.hibernate.dialect.Oracle10gDialect
        driverClassName: oracle.jdbc.driver.OracleDriver
        username: rip
        password: password
        dbCreate: validate
        url: jdbc:oracle:thin:@127.0.0.1:345:coolio

environments:
    development:
        dataSources:
            dataSource:
                dbCreate: create-drop
                url: jdbc:h2:mem:devDb;MVCC=TRUE
    test:
        dataSources:
            dataSource:
                dbCreate: update
                url: jdbc:h2:mem:testDb;MVCC=TRUE
    production:
        dataSources:
            dataSource:
                dbCreate: update
                url: jdbc:h2:mem:prodDb;MVCC=TRUE

In my DatabaseService, I have the following code to try and inject the dataSource bean:

class DatabaseService {

    static datasource = 'raw'
    DataSource dataSource

    public void testMyDb(User user) {
        try {
            println("we are in here with : " +    dataSource.getConnection().getMetaData().getURL())
            registerUser(new Sql(dataSource), user)
        } catch (SQLException e) {
            LOGGER.error("unable to register the user", e)
            throw e
        }
    }

    public void registerDeveloper(Sql sql, User user) {
            sql.call("{call isertUser(?)}", [user.name])
    }

The print statement in the DatabaseService file prints out:

    we are in here with : jdbc:h2:mem:testDb

However, it should print out:

    we are in here with : jdbc:oracle:thin:@127.0.0.1:345:coolio

What am I doing wrong? Why is it that the original Datasource bean is the one that gets instantiated?

UPDATED ATTEMPTS (1): I see a good thread here: https://github.com/grails/grails-core/issues/9690 , but even after replacing

 static datasource = 'raw' 

with

 @Autowired 
 @Qualifier('dataSource_raw')

nothing changes. If I grab the Springs ApplicationContext, and print out the beans, dataSource_raw is indeed one of them.

UPDATED ATTEMPTS (2): I have tried to remove the entire environment section, with nothing changing.

Upvotes: 3

Views: 1952

Answers (2)

ricardogobbo
ricardogobbo

Reputation: 1740

You can also declare as follows

def dataSource_raw

Without @Resource annotation

Upvotes: 0

Sandeep Poonia
Sandeep Poonia

Reputation: 2188

Updated answer:

This seems to be a bug with grails 3. Not sure if it has been fixed in newer versions (>3.0.11). Even if we specify bean name with @Autowired and @Qualifier annotation, grails injects the default bean in case of dataSource, transactionManager and sessionFactory. This could be the case with other beans also, but I have tested only these three. I haven't tested the behaviour with domains or controllers.

To overcome this, what you can do is, instead of using these default names, use custom name along with @Autowired and @Qualifier or @Resource annotation.

With following way, you will get beans for default data source, even if you are specifying to use a different bean:

@Resource(name = "dataSource_raw")
DataSource dataSource

@Resource(name = "transactionManager_raw")
PlatformTransactionManager transactionManager

@Resource(name = "sessionFactory_raw")
SessionFactory sessionFactory

But with custom names, the bean with the name specified using @Qualifier or @Resource will be injected:

@Resource(name = "dataSource_raw")
DataSource rawDataSource

@Resource(name = "transactionManager_raw")
PlatformTransactionManager rawTransactionManager

@Resource(name = "sessionFactory_raw")
SessionFactory rawSessionFactory

Upvotes: 2

Related Questions