Monday, December 13, 2010

Grails AS400 RPG Connection Pool

In my last post I said: "For the most part, I did not have to do anything overly special to work with the AS400" in the development of the AS400-based Kettler USA retail site. The one area that took a bit of Grails-magic was some direct calls to RPG and some indirect calls to RPG via messages. The direct calls were done via JDBC stored procedures, so the standard JDBC connection pool set up by the Grails DataSource.groovy configuration worked fine. But for the message-base communication, I used AS400 data queues -- which are not supported by JDBC. So I needed to create an AS400 connection object. You really don't want to create an AS400 connection object for each request. Instead you want to use IBM's AS400 Connection Pool.

Once the AS400 Connection Pool is available, I'm able to use it in my service class like so:

class PreAuthorizationService implements Serializable {
def as400ConnPool
String preAuth(Cart cart){
AS400 conn = getConnection()
...

But where do you create the AS400 Connection Pool and when? Grails makes that easy.

In grails-app/conf/spring/resources.groovy place the following code:

import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH
beans = {
if (CH.config.dataSource.driverClassName ==
'com.ibm.as400.access.AS400JDBCDriver') {
as400ConnPool(AS400ConnPoolFactory) {bean ->
ip = CH.config.iseriesIPAddress
userId = CH.config.iseriesUserId
password = CH.config.iseriesPwd
}
}
}

I put the IP, username, and password in Config.groovy (hence the use of ConfigurationHolder. Also note that, because I often use a local MySQL-based AS400-connection-less test environment, I predicate the creation of the AS400 connection so it is only created if the IBM driver was active. The IBM AS400 Connection Pool needs a bit of Spring infrastructure, which I coded in my AS400ConnPoolFactory wrapper class:

import org.springframework.beans.factory.FactoryBean
import org.springframework.beans.factory.InitializingBean

import com.ibm.as400.access.AS400
import com.ibm.as400.access.AS400ConnectionPool

class AS400ConnPoolFactory implements FactoryBean {
String ip
String userId
String password

public Object getObject() throws Exception {
// note: try/catch removed for brevity
AS400ConnectionPool as400ConnPool = new AS400ConnectionPool()
as400ConnPool.setMaxConnections(128)
as400ConnPool.fill(ip, userId, password, AS400.COMMAND, 5)
return as400ConnPool
}
public Class getObjectType() {AS400ConnectionPool.class}
public boolean isSingleton() {true}
}


It's all pretty simple. AS400 connection pools made easy by Grails!

1 comment:

Jon said...

Thanks for the example Don. What I don't understand is how the fill() works. The JavaDocs for that class states that it "Preconnects a specified number of connections to a specific system, userID, password, and service." But then to actually get a connection from the connection pool you have to call the getConnection(String 1, ...) and pass in the same set of connection parameters. Is that what you have to do or am I looking at this wrong?