Categories

Bash rocks

Whenever I get a new Windows development machine, the first thing I do is install some software to actually make it usable. First off, it’s usually Cygwin.
This allows me to work on a Windows filesystem using a proper set of tools, including the venerable Bash shell. This shell has so many tricks and shortcuts up its sleeve, it’s incredible. One of my favourites (and one I always forget how to use in between using it) is variable substitution. The Win32 CLI offers a watered-down version of this as well, but Bash allows you to do things like this:

for i in $(dir *.MD5); do mv -f$i ${i%.MD5}.md5; done Note the variable substitution bit in the curly braces, that says “return everything except the shortest match starting from the right-hand-side of the variable$i that matches the pattern .MD5.

Categories

Easy Testing with AbstractTransactionalSpringContextTests

Spring 1.2 has got some nice support for database testing. Specifically, it has the class AbstractTransactionalSpringContextTests, which will execute its tests within an individual transaction, and then rollback at the end of each test, unless you specify otherwise by calling setComplete(). This class in turn extends the class AbstractDependencyInjectionSpringContextTests, which uses field injection to populate its data. Field injection looks up beans in the current context by name, rather than type. So for instance, our PersistentTestCase class can now look like:

 import org.hibernate.SessionFactory; import org.springframework.test.AbstractTransactionalSpringContextTests; public class PersistentTestCase extends AbstractTransactionalSpringContextTests {     protected SessionFactory testSessionFactory;   //wired by type     protected ReferenceData referenceData;     protected PersistentTestCase()     {         super();         //setDefaultRollback(false);          setPopulateProtectedVariables(true);     }     protected String[] getConfigLocations()     {         return new String[]         {             "classpath:application_test_context.xml"         };     }     protected void flushSession(){         testSessionFactory.getCurrentSession().flush();     }     protected void clearSession(){         flushSession();         testSessionFactory.getCurrentSession().clear();     }     public void setReferenceData(ReferenceData p_referenceData)     {         referenceData = p_referenceData;     } }

The neat thing about this is that we have a whole bunch of reference data that is injected into the class and populated automatically – just by declaring the data as a protected field, calling setPopulateProtectedVariables(true), and declaring the reference data bean in the application-context.xml with the correct name. Field-based injection will take care of the rest. Very easy, and it makes things nice and neat. Another nice feature is that contexts can be cached, and not reloaded and reinitialized every time across tests, which can save a lot of time if you’re using Hibernate’s create-drop mode, and it spends a long time initializing constraints.

Categories

Eclipse package-info bug solved

I finally found the cause of the Eclipse package-info.java bug I mentioned earlier. I took a look at the .class files generated by IDEA and Eclipse and compared them, first using javap, and then using good old Vim’s built in Hex mode. Using a copy of the class file format specification (updated for Java 5), I was able to decipher the .class files and find a few interesting things.

For starters, here is the class file format:

ClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; }

First of all, the constant pool layout seems to be arbitrary, and there doesn’t seem to be any fixed order on where constants appear in the pool versus how they are defined in the source code. This stands to reason, as the constant pool is a lookup table, after all, and it should be irrelevant where they physically appear, as long as they are indexed correctly.

The second issue was actually tracking down what Eclipse and IDEA did differently. I had a feeling that the issue may have resided in the attributes section of the class file, but as it turned out, the error turned out to be in the access_info field of the class file. The access_info field is defined as:

 Flag Name Value Interpretation ACC_PUBLIC 0x0001 Declared public; may be accessed from outside its package. ACC_FINAL 0x0010 Declared final; no subclasses allowed. ACC_SUPER 0x0020 Treat superclass methods specially when invoked by the invokespecial instruction. ACC_INTERFACE 0x0200 Is an interface, not a class. ACC_ABSTRACT 0x0400 Declared abstract; may not be instantiated. ACC_ANNOTATION 0x0400 Declared as an annotation type ACC_ENUM 0x0400 Declared as an enum type.

The value of this field was 0x1600 for Eclipse, but 0x0200 for IDEA. The Eclipse value was (I presume) constructed by using ACC_INTERFACE | ACC_ABSTRACT | ACC_SYNTHETIC. The ClassLoader choked when it saw the synthetic attribute. This bug has now been fixed. Oddly, the “bug” is technically correct – the synthetic attribute should be perfectly valid for a package-info class file. Apparently it will be in 6.0.

The strange thing is that the IDEA-generated access_info field is 0x0200 (ACC_INTERFACE), when strictly in accordance with the spec, it should be 0x0600 (ACC_INTERFACE | ACC_ABSTRACT), and technically is erroneous. I’m not sure why the CM does not flag it as such.

The last point I noticed is that the extensible attribute system that Sun built into the class file format was a stroke of genius. This is what supports the JDK 5 annotation system, and has previously allowed vendors to extend the class format in ways never thought possible.