Search code examples
grailsdatasourcemultiple-databases

Define optional (multiple) datasource in Grails


I am currently developing a Grails plugin using Grails 2.3.11 and familiar using multiple datasources. But now I want that my domain objects provided by that plugin CAN use a different dataSource (because of performance reasons all data can be stored in a different database).

The problem is, that this second datasource is optional, which means, the user can define a second datasource in tomcat (accessible via JNDI), but doesn't have to. This is an important point: the user can define a second dataSource in the servlet container and the Grails application has to check if there is a second dataSource available!

Be to more specific: I've a domain class:

class MyDomain {

    static mapping = {
        datasource('optionalDS')
    }
}

My DataSource.groovy:

dataSource {
    jndiName = "..."
}

dataSource_optionalDS {
    jndiName = "..."
}

The problem is, that this will fail if the user hasn't configured the JNDI name for that optional datasource (because it is optional, he doesn't have to).

I tried to create a delegating datasource instead:

class OptionalDataSource extends DelegatingDataSource {

    ...
    // the main purpose is to check, if the optional DS
    // can be created using JNDI. If this fails, the default
    // DS is used
    setTagetDataSource(dataSource)
    ...

}

And in my Plugin descriptor:

def doWithSpring = {
    dataSource_optionalDS(OptionalDataSource) {
        // set default DS in case optional can not be created
        dataSource = ref('dataSource')
    }
}

The problem with this solution is, that the dataSource optionalDS is not available. If I try to read data, i.e. MyDomain.findAll() I get the following error:

Methond on class MyDomain was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.

I don't understand why, because I can define the default dataSource that way.

So, my question is: How can I define an optional dataSource in Grails?


Solution

  • How about looking up the JNDI dataSource in DataSource.groovy and then if it exists declaring your optional dataSource. Something like following

        //default dataSource
        dataSource {
            jndiName = "..."
        } 
    
        //optional dataSource
        //let's first lookup the JNDI dataSource
        def jndiDataSource
    
        try {
            jndiDataSource = InitialContext.doLookup("...")
        } 
        catch(NamingException ne) {}
    
        //now if jndiDataSource exists we can declare the optional dataSource
        if(jndiDataSource) {
            dataSource_optionalDS {
                jndiName = "..."
            }
        }
    

    I was looking for an alternate lightwight method for just checking if the JNDI dataSource exists instead of looking it up. But no luck.