Archive for May, 2007

Rails and DB2 data types

When creating a table in a Rails migration, you have to specify data types using platform-agnostic names. The mapping of Rails types onto DB2 types is defined in ibm_db_adapter.rb:

:primary_key => @servertype.primary_key,
:string      => { :name => "varchar", :limit => 255 },
:text        => { :name => "clob" },
:integer     => { :name => "integer" },
:float       => { :name => "float" },
:datetime    => { :name => "timestamp" },
:timestamp   => { :name => "timestamp" },
:time        => { :name => "time" },
:date        => { :name => "date" },
:binary      => { :name => "blob" },

# A boolean can be represented  by a smallint,
# adopting the convention that False is 0 and True is 1
:boolean     => { :name => "smallint"},
:xml         => { :name => "xml"},
:decimal     => { :name => "decimal" }

Useful Resources

InfoCenter | DB2 Data Types
dW | DB2 and Ruby on Rails, Part 1 (May 2007)
dW | An Introduction to Ruby on Rails for DB2 Developers (June 2006)

The DB2 adapter is now called ibm_db. You can refresh your installation by typing gem install ibm_db at the command line and choosing the latest win32 release.

Reflection in Javascript

It’s very easy to do reflection in Javascript. Reflection is when your code looks onto itself to discover its variables and functions. It allows two different Javascript codebases to learn about each other, and it’s useful for exploring third-party APIs.

Preamble

In Javascript, all objects are hashes/associative arrays/dictionaries. A hash is like an array, except that values are associated with unique key string rather than a numeric index.

Adding a new variable to an object is as simple as assigning a new value to a key in the object.

You can declare everything in place:

var o = {
	count: 0,
	name: 'Jane Doe',
	greeting: function() { return "Hi"; }
};
o.greeting();

Or you can start with a blank object and assign things later:

var o = {};

o.count = 0;
o.name = 'Jane Doe';
o.greeting = function() { return "Hi"; };

o.greeting();

Or you can do the same, but in a different notation:

var o = {};

o['count'] = 0;
o['name'] = 'Jane Doe';
o['greeting'] = function() { return "Hi"; }

o.greeting();

The last is especially handy because it allows you to go from the string name of the variable to the variable without the performance penalties of eval().

{} is synonymous with new Object().

Reflection

The loop below pops up a dialog box with the name and value of every variable in object:

for (var member in object) {
	alert('Name: ' + member);
	alert('Value: ' + object[member]);
}

Everything in Javascript is an object. Functions are objects! document and window are objects. The most reliable reference for Javascript in a given browser is reflection into its innards.

Finally, some slightly more useful code:

/**
	Returns the names of all the obj's
	 variables and functions in a sorted
	 array
*/
function getMembers(obj) {
	var members = new Array();
	var i = 0;

	for (var member in obj) {
		members[i] = member;
		i++;
	}

	return members.sort();
}

/**
	Print the names of all the obj's variables
	 and functions in an HTML element with id
*/
function printMembers(obj, id) {
	var members = getMembers(obj);
	var display = document.getElementById(id);

	for (var i = 0; i < members.length; i++) {
		var member = members[i];
		var value = obj[member];
		display.innerHTML += member + ' = ';
		display.innerHTML += value + '<br>';
	}
}

More sophisticated uses are left as an exercise for the reader. :-)

No implementation defined for org.apache.commons.logging.LogFactory

While writing a DB2 stored procedure that invoked a SOAP/WSDL web service using Apache Axis as part of WSIF, I ran into this doozie:

org.apache.commons.discovery.DiscoveryException:
No implementation defined for org.apache.commons.logging.LogFactory

Ultimately, it’s caused by a too restrictive lib/security/java.policy file that ships with DB2.

Wrong Solution

The standard way to define an implementation is to create the following commons-logging.properties file and place it anywhere in your CLASSPATH (such as the root of a JAR file):

# Default
#org.apache.commons.logging.LogFactory = org.apache.commons.logging.impl.LogFactoryImpl

# SimpleLog
#org.apache.commons.logging.Log = org.apache.commons.logging.impl.SimpleLog 

# JDK 1.4 logger
#org.apache.commons.logging.Log = org.apache.commons.logging.impl.Jdk14Logger

# Avalon Toolkit
#org.apache.commons.logging.Log = org.apache.commons.logging.impl.LogKitLogger

# Log4j (Recommended by Axis)
org.apache.commons.logging.Log = org.apache.commons.logging.impl.Log4JLogger

Alternatively, you can set the org.apache.commons.logging.Log configuration attribute for LogFactory programmatically.

Right Solution

Solution: Running an Axis SOAP client in Domino [or DB2]

My DB2 is installed into C:\Program Files\IBM\SQLLIB

1. Copy all your JARs to C:\Program Files\IBM\SQLLIB\java\jdk\jre\lib\ext
2. Open C:\Program Files\IBM\SQLLIB\java\jdk\jre\lib\security\
3. Open java.policy
4. Add:

permission java.util.PropertyPermission "java.protocol.handler.pkgs", "write";

5. Restart DB2