iSeries systems and Ruby are separate universes right now; I know of no native Ruby way to connect to an AS400 system. However, with the help of Java we can bridge the gap.
Probably the simplest example is connecting to an iSeries system using JDBC to select from some tables, and with the right libraries it is straightforward. It’s also fun to be doing some nifty quick Ruby but with some preexisting and proven Java libraries.
Also, if you use Java and Ruby, definitely put arton’s RubyJavaBridge in your pocket; you’ll end up using it more than once.
What you’ll need:
- Ruby (well yea)
- Java (ok)
- access to an AS400 system (that’s the whole point here…)
For testing, I’ve been using a free account available from Holger Scherer Software und Beratung. - jt400.jar jdbc drivers from JTOpen, a great open-source Java library for AS400 access.
- RubyJavaBridge is the keystone for this.
Installing the software is the hardest part of this exercise, but it’s more tedium than anything. Once you’ve got it all downloaded and running the fun can begin.
require 'rjb'
Rjb::load('jtopen_5_0/lib/jt400.jar',['-Djdbc.drivers=com.ibm.as400.access.AS400JDBCDriver'])
DriverManager = Rjb::import('java.sql.DriverManager')
begin
connection = DriverManager.getConnection('jdbc:as400://as400.holgerscherer.de','YOUR_USERNAME','YOUR_PASSWORD')
statement = connection.prepareStatement("SELECT count(*) FROM SYSIBM.TABLES")
result_set = statement.executeQuery
while(result_set.next())
puts result_set.getObject(1).toString
end
ensure
result_set.close if defined?(result_set) && !statement.nil?
statement.close if defined?(statement) && !statement.nil?
connection.close if defined?(connection) && !connection.nil?
end
$ ruby as400_rjb.rb
19138
Very readable, I think. Java and Ruby actually play well together given half the chance and arton’s fantastic bridge.
Compare this with the pure Java implementation.
import java.sql.*;
public class As400Jdbc
{
public static void main(String args[])
{
Connection connection = null;
try
{
connection = DriverManager.getConnection("jdbc:as400://as400.holgerscherer.de","USER","PASS");
PreparedStatement statement = connection.prepareStatement("SELECT COUNT(*) FROM SYSIBM.TABLES");
ResultSet resultSet = statement.executeQuery();
while(resultSet.next())
{
System.out.println(resultSet.getObject(1));
}
}
catch(SQLException e)
{
throw new RuntimeException(e);
}
finally
{
try{ if(connection!=null) connection.close(); }
catch(SQLException e)
{
throw new RuntimeException(e);
}
}
}
}
$ javac As400Jdbc.java
$ java -cp jtopen_5_0/lib/jt400.jar:. -Djdbc.drivers=com.ibm.as400.access.AS400JDBCDriver As400Jdbc
19138
The Ruby code and the Java code are nearly one-for-one so far, and that’s fine. Still, let’s see if we can’t pull the Java code more into Ruby’s world. The begin...end
stuff gets tiresome; it would be nice if these Java classes could handle the resource allocation and disposal drudgery for us, using blocks.
require 'rjb'
Rjb::load('/home/darren/dload/jtopen_5_0/lib/jt400.jar',['-Djdbc.drivers=com.ibm.as400.access.AS400JDBCDriver'])
DriverManager = Rjb::import('java.sql.DriverManager')
class <<DriverManager
def with_connection(*args)
begin
connection = DriverManager.getConnection(*args)
yield connection
ensure
connection.close
end
end
end
DriverManager.with_connection('jdbc:as400://as400.holgerscherer.de','USER_NAME','USER_PASS') do |conn|
statement = conn.prepareStatement("SELECT count(*) FROM SYSIBM.TABLES")
result_set = statement.executeQuery()
result_set.next()
puts result_set.getObject(1).toString
end
I know I’m a geek because stuff like this makes me giggle. So many worlds are colliding here–Ruby, Java, AS400, DB2, the client system (Linux in this case)–and it all comes together so nicely.
I’m not saying I’d build an app out of this, but it will more than suffice for ad-hoc queries and quick scripts.