Friday, September 11, 2009

Grails: Multiple datasources without GORM

Who's playing around with Grails knows about GORM. GORM is Grails' object relational mapping (ORM) implementation. GORM is built on the top of Hibernate and enables persistence. The configuration of the database used for persistence is in the file grails-app/conf/DataSource.groovy. The application might need to access other databases for reasons other than persistence. It might be necessary to distinguish different sources for development, test or production (the Grails standard environments). In this case it is possible to leverage Spring creating the file grails-app/conf/srping/resources.groovy with a content similar to the following, which is setting up the connection to the Virtuoso triple store:

import org.apache.commons.dbcp.BasicDataSource

/*
* @author Paolo Ciccarese
*
* The virtuoso data source has been defined here to not
* interfere with the GORM datasource in the file
* grails-app/conf/DataSource.groovy
*/

beans = {
// Virtuoso triple store
virtuosoDataSourceDevelopment(BasicDataSource) {
driverClassName = "virtuoso.jdbc3.Driver"
url="jdbc:virtuoso://localhost:1111"
username="dba"
password="dba"
}
virtuosoDataSourceTest(BasicDataSource) {
driverClassName = "virtuoso.jdbc3.Driver"
url="jdbc:virtuoso://blah.org:1111"
username="dba"
password="dba"
}
virtuosoDataSourceProduction(BasicDataSource) {
// Here the details of the production data source
}
}
BasicDataSource has been used as it guarantees connection pooling. In some examples, instead of that class you can find org.springframework.jdbc.datasource.DriverManagerDataSource . Reading the documentation: This class is not an actual connection pool; it does not actually pool Connections. It just serves as simple replacement for a full-blown connection pool, implementing the same standard interface, but creating new Connections on every call. This might create problems with Virtuoso in the case of numerous queries. Once we defined the data sources it is possible to define a service (> grails create-service) for providing the right one according to the current environment:

class SparqlService {

def transactional = false

def virtuosoDataSourceProduction
def virtuosoDataSourceDevelopment
def virtuosoDataSourceTest

private static final String TEST = "test"

def getDataSource() {
if(grails.util.GrailsUtil.isDevelopmentEnv())
return virtuosoDataSourceDevelopment
else if(grails.util.GrailsUtil.getEnvironment()==TEST)
return virtuosoDataSourceTest
else
return virtuosoDataSourceProduction
}
}
Now it will be possible, for other services to use the one just defined. Something like:

class SparqlQueryService {

def sparqlService

boolean transactional = false

public List<Map<String, Object>> getSparqlResultRowMaps(String query){
log.info("Running query: " + query);
JdbcTemplate jdbcTemplate = new JdbcTemplate(sparqlService.getDataSource())
.....
return results;
}

....
}

Where the sparqlService is injected. Thus when a query is needed is sufficient to refer to sparqlQueryService, which will take care of selecting the right datasource.

No comments: