Friday, September 7, 2012

Strange build problem with Grails 2.0 and plugin dependencies

I am checking out the db-reverse-engineer plugin for Grails 2 and ran into a strange error running.
grails db-reverse-engineer
I reran with this extra option
grails db-reverse-engineer --verbose
This was the output
Base Directory: C:\dev\fourgablesguy
| Loading Grails 2.0.4
* FOURGABLES_REPOSITORY=C:/fourgablesguy
| Configuring classpath.
| Environment set to development.....
| Packaging Grails application.....
| Compiling 1 source files
  [groovyc] Compiling 1 source file to C:\dev\fourgablesguy\target\classes
| Compiling 1 source files.....
     [copy] Copying 1 file to C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy
webxml.WebxmlGrailsPlugin Did not find application config file: WebXmlConfig
| Packaging Grails application.
| Compiling 1 source files
  [groovyc] Compiling 1 source file to C:\dev\fourgablesguy\target\classes
| Compiling 1 source files.....
util.GrailsUtil [DEPRECATED] Property or method [getReference] of class [org.codehaus.groovy.grails.commons.AbstractGrailsClass] is deprecated in [2.0.4] and will be removed in future releases
     [copy] Copying 1 file to C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy
webxml.WebxmlGrailsPlugin Did not find application config file: WebXmlConfig
util.GrailsUtil [DEPRECATED] Property or method [getReference] of class [org.codehaus.groovy.grails.commons.AbstractGrailsClass] is deprecated in [2.0.4] and will be removed in future releases
| Starting database reverse engineering, connecting to 'jdbc:oracle:thin:@192.168.10.89:1522:nddev08' as 'hmcdaniel_fourgablesguy' .....
| Compiling 10 source files
  [groovyc] Compiling 10 source files to C:\dev\fourgablesguy\target\revengclasses
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\GrailsCfg2JavaTool.groovy
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\GrailsEntityPOJOClass.groovy
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\GrailsJdbcBinder.groovy
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\GrailsJdbcMetaDataConfiguration.groovy
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\GrailsPojoExporter.groovy
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\GrailsReverseEngineeringStrategy.groovy
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\GrailsTemplateProducer.groovy
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\Reenigne.groovy
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\RevengRunner.groovy
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\ReverseEngineerProgressListener.groovy
  [groovyc] The option includeAntRuntime cannot be set on the contained  element. The option will be ignored
Unable to obtain resource from C:\Users\fourgablesguy\.grails\ivy-cache\log4j\log4j\jars\log4j-1.2.15.jar: java.util.zip.ZipException: invalid CEN header (bad signature)
  [groovyc] Unable to obtain resource from C:\Users\fourgablesguy\.grails\ivy-cache\log4j\log4j\jars\log4j-1.2.15.jar: 
  [groovyc] java.util.zip.ZipException: invalid CEN header (bad signature)
  [groovyc]  at java.util.zip.ZipFile.open(Native Method)
  [groovyc]  at java.util.zip.ZipFile.(Unknown Source)
  [groovyc]  at java.util.jar.JarFile.(Unknown Source)
  [groovyc]  at org.apache.tools.ant.AntClassLoader.getResourceURL(AntClassLoader.java:1002)
  [groovyc]  at org.apache.tools.ant.AntClassLoader$ResourceEnumeration.findNextResource(AntClassLoader.java:145)
  [groovyc]  at org.apache.tools.ant.AntClassLoader$ResourceEnumeration.(AntClassLoader.java:109)
  [groovyc]  at org.apache.tools.ant.AntClassLoader.findResources(AntClassLoader.java:949)
  [groovyc]  at org.apache.tools.ant.AntClassLoader.findResources(AntClassLoader.java:931)
  [groovyc]  at java.lang.ClassLoader.getResources(Unknown Source)
  [groovyc]  at org.codehaus.groovy.transform.ASTTransformationVisitor.doAddGlobalTransforms(ASTTransformationVisitor.java:194)
  [groovyc]  at org.codehaus.groovy.transform.ASTTransformationVisitor.addGlobalTransforms(ASTTransformationVisitor.java:187)
  [groovyc]  at org.codehaus.groovy.transform.ASTTransformationVisitor.addPhaseOperations(ASTTransformationVisitor.java:150)
  [groovyc]  at org.codehaus.groovy.control.CompilationUnit.(CompilationUnit.java:185)
  [groovyc]  at org.codehaus.groovy.control.CompilationUnit.(CompilationUnit.java:117)
  [groovyc]  at org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit.(JavaAwareCompilationUnit.java:54)
  [groovyc]  at org.codehaus.groovy.ant.Groovyc.makeCompileUnit(Groovyc.java:965)
  [groovyc]  at org.codehaus.groovy.grails.compiler.Grailsc.makeCompileUnit(Grailsc.java:34)
  [groovyc]  at org.codehaus.groovy.ant.Groovyc.compile(Groovyc.java:909)
  [groovyc]  at org.codehaus.groovy.grails.compiler.Grailsc.compile(Grailsc.java:79)
  [groovyc]  at org.codehaus.groovy.ant.Groovyc.execute(Groovyc.java:607)
  [groovyc]  at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
  [groovyc]  at sun.reflect.GeneratedMethodAccessor101.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
  [groovyc]  at groovy.util.AntBuilder.performTask(AntBuilder.java:260)
  [groovyc]  at groovy.util.AntBuilder.nodeCompleted(AntBuilder.java:220)
  [groovyc]  at groovy.util.BuilderSupport.doInvokeMethod(BuilderSupport.java:147)
  [groovyc]  at groovy.util.AntBuilder.doInvokeMethod(AntBuilder.java:170)
  [groovyc]  at groovy.util.BuilderSupport.invokeMethod(BuilderSupport.java:64)
  [groovyc]  at org.codehaus.gant.GantBuilder.invokeMethod(GantBuilder.java:99)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:45)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
  [groovyc]  at DbReverseEngineer$_run_closure1.doCall(DbReverseEngineer:51)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
  [groovyc]  at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
  [groovyc]  at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
  [groovyc]  at groovy.lang.DelegatingMetaClass.invokeMethod(DelegatingMetaClass.java:149)
  [groovyc]  at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
  [groovyc]  at groovy.lang.Closure.call(Closure.java:412)
  [groovyc]  at groovy.lang.Closure.call(Closure.java:425)
  [groovyc]  at sun.reflect.GeneratedMethodAccessor72.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
  [groovyc]  at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
  [groovyc]  at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
  [groovyc]  at groovy.lang.DelegatingMetaClass.invokeMethod(DelegatingMetaClass.java:149)
  [groovyc]  at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
  [groovyc]  at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16_closure18.doCall(GantBinding.groovy:185)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
  [groovyc]  at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16_closure18.doCall(GantBinding.groovy)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
  [groovyc]  at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
  [groovyc]  at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
  [groovyc]  at groovy.lang.Closure.call(Closure.java:412)
  [groovyc]  at groovy.lang.Closure.call(Closure.java:406)
  [groovyc]  at java_util_concurrent_Callable$call.call(Unknown Source)
  [groovyc]  at org.codehaus.gant.GantBinding.withTargetEvent(GantBinding.groovy:90)
  [groovyc]  at org.codehaus.gant.GantBinding.this$4$withTargetEvent(GantBinding.groovy)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
  [groovyc]  at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
  [groovyc]  at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:992)
  [groovyc]  at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:697)
  [groovyc]  at groovy.lang.GroovyObjectSupport.invokeMethod(GroovyObjectSupport.java:44)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethodOnGroovyObject(MetaClassImpl.java:1112)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1006)
  [groovyc]  at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149)
  [groovyc]  at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16.doCall(GantBinding.groovy:185)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
  [groovyc]  at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16.doCall(GantBinding.groovy)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
  [groovyc]  at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
  [groovyc]  at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
  [groovyc]  at groovy.lang.Closure.call(Closure.java:412)
  [groovyc]  at groovy.lang.Closure.call(Closure.java:406)
  [groovyc]  at java_util_concurrent_Callable$call.call(Unknown Source)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
  [groovyc]  at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
  [groovyc]  at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
  [groovyc]  at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
  [groovyc]  at groovy.lang.Closure.call(Closure.java:412)
  [groovyc]  at groovy.lang.Closure.call(Closure.java:425)
  [groovyc]  at groovy.lang.Closure$call.call(Unknown Source)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
  [groovyc]  at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
  [groovyc]  at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
  [groovyc]  at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
  [groovyc]  at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
  [groovyc]  at groovy.lang.Closure.call(Closure.java:412)
  [groovyc]  at groovy.lang.Closure.call(Closure.java:406)
  [groovyc]  at java_util_concurrent_Callable$call.call(Unknown Source)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
  [groovyc]  at gant.Gant.withBuildListeners(Gant.groovy:427)
  [groovyc]  at gant.Gant.this$2$withBuildListeners(Gant.groovy)
  [groovyc]  at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
  [groovyc]  at gant.Gant.dispatch(Gant.groovy:415)
  [groovyc]  at gant.Gant.this$2$dispatch(Gant.groovy)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
  [groovyc]  at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
  [groovyc]  at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
  [groovyc]  at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:699)
  [groovyc]  at gant.Gant.invokeMethod(Gant.groovy)
  [groovyc]  at groovy.lang.GroovyObject$invokeMethod.callCurrent(Unknown Source)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145)
  [groovyc]  at gant.Gant.executeTargets(Gant.groovy:591)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
  [groovyc]  at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145)
  [groovyc]  at gant.Gant.executeTargets(Gant.groovy:590)
  [groovyc]  at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeWithGantInstance(GrailsScriptRunner.java:693)
  [groovyc]  at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeScriptFile(GrailsScriptRunner.java:497)
  [groovyc]  at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeScriptWithCaching(GrailsScriptRunner.java:432)
  [groovyc]  at org.codehaus.groovy.grails.cli.GrailsScriptRunner.callPluginOrGrailsScript(GrailsScriptRunner.java:383)
  [groovyc]  at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeCommand(GrailsScriptRunner.java:362)
  [groovyc]  at org.codehaus.groovy.grails.cli.GrailsScriptRunner.main(GrailsScriptRunner.java:228)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [groovyc]  at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  [groovyc]  at java.lang.reflect.Method.invoke(Unknown Source)
  [groovyc]  at org.codehaus.groovy.grails.cli.support.GrailsStarter.rootLoader(GrailsStarter.java:234)
  [groovyc]  at org.codehaus.groovy.grails.cli.support.GrailsStarter.main(GrailsStarter.java:262)
  [groovyc] org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\GrailsReverseEngineeringStrategy.groovy: 19: unable to resolve class org.apache.log4j.Logger
  [groovyc]  @ line 19, column 1.
  [groovyc]    import org.apache.log4j.Logger
  [groovyc]    ^
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\GrailsTemplateProducer.groovy: 17: unable to resolve class org.apache.log4j.Logger
  [groovyc]  @ line 17, column 1.
  [groovyc]    import org.apache.log4j.Logger
  [groovyc]    ^
  [groovyc] C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\ReverseEngineerProgressListener.groovy: 17: unable to resolve class org.apache.log4j.Logger
  [groovyc]  @ line 17, column 1.
  [groovyc]    import org.apache.log4j.Logger
  [groovyc]    ^
  [groovyc] 3 errors
| Compiling 10 source files.
| Error Error executing script DbReverseEngineer: : Compilation Failed
: Compilation Failed
 at org.codehaus.groovy.ant.Groovyc.compile(Groovyc.java:924)
 at org.codehaus.groovy.grails.compiler.Grailsc.compile(Grailsc.java:79)
 at org.codehaus.groovy.ant.Groovyc.execute(Groovyc.java:607)
 at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
 at sun.reflect.GeneratedMethodAccessor101.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
 at groovy.util.AntBuilder.performTask(AntBuilder.java:260)
 at groovy.util.AntBuilder.nodeCompleted(AntBuilder.java:220)
 at groovy.util.BuilderSupport.doInvokeMethod(BuilderSupport.java:147)
 at groovy.util.AntBuilder.doInvokeMethod(AntBuilder.java:170)
 at groovy.util.BuilderSupport.invokeMethod(BuilderSupport.java:64)
 at org.codehaus.gant.GantBuilder.invokeMethod(GantBuilder.java:99)
 at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:45)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
 at DbReverseEngineer$_run_closure1.doCall(DbReverseEngineer:51)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
 at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
 at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
 at groovy.lang.DelegatingMetaClass.invokeMethod(DelegatingMetaClass.java:149)
 at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
 at groovy.lang.Closure.call(Closure.java:412)
 at groovy.lang.Closure.call(Closure.java:425)
 at sun.reflect.GeneratedMethodAccessor72.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
 at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
 at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
 at groovy.lang.DelegatingMetaClass.invokeMethod(DelegatingMetaClass.java:149)
 at org.codehaus.gant.GantMetaClass.invokeMethod(GantMetaClass.java:133)
 at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
 at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
 at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16_closure18.doCall(GantBinding.groovy:185)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226)
 at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
 at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16_closure18.doCall(GantBinding.groovy)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
 at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
 at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
 at groovy.lang.Closure.call(Closure.java:412)
 at groovy.lang.Closure.call(Closure.java:406)
 at java_util_concurrent_Callable$call.call(Unknown Source)
 at org.codehaus.gant.GantBinding.withTargetEvent(GantBinding.groovy:90)
 at org.codehaus.gant.GantBinding.this$4$withTargetEvent(GantBinding.groovy)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
 at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
 at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:992)
 at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:697)
 at groovy.lang.GroovyObjectSupport.invokeMethod(GroovyObjectSupport.java:44)
 at groovy.lang.MetaClassImpl.invokeMethodOnGroovyObject(MetaClassImpl.java:1112)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1006)
 at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
 at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149)
 at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16.doCall(GantBinding.groovy:185)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226)
 at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
 at org.codehaus.gant.GantBinding$_initializeGantBinding_closure5_closure16.doCall(GantBinding.groovy)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
 at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
 at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
 at groovy.lang.Closure.call(Closure.java:412)
 at groovy.lang.Closure.call(Closure.java:406)
 at java_util_concurrent_Callable$call.call(Unknown Source)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
 at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
 at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
 at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
 at groovy.lang.Closure.call(Closure.java:412)
 at groovy.lang.Closure.call(Closure.java:425)
 at groovy.lang.Closure$call.call(Unknown Source)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
 at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226)
 at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
 at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
 at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
 at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
 at groovy.lang.Closure.call(Closure.java:412)
 at groovy.lang.Closure.call(Closure.java:406)
 at java_util_concurrent_Callable$call.call(Unknown Source)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
 at gant.Gant.withBuildListeners(Gant.groovy:427)
 at gant.Gant.this$2$withBuildListeners(Gant.groovy)
 at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
 at gant.Gant.dispatch(Gant.groovy:415)
 at gant.Gant.this$2$dispatch(Gant.groovy)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
 at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
 at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:877)
 at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:699)
 at gant.Gant.invokeMethod(Gant.groovy)
 at groovy.lang.GroovyObject$invokeMethod.callCurrent(Unknown Source)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145)
 at gant.Gant.executeTargets(Gant.groovy:591)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:226)
 at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:52)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145)
 at gant.Gant.executeTargets(Gant.groovy:590)
 at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeWithGantInstance(GrailsScriptRunner.java:693)
 at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeScriptFile(GrailsScriptRunner.java:497)
 at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeScriptWithCaching(GrailsScriptRunner.java:432)
 at org.codehaus.groovy.grails.cli.GrailsScriptRunner.callPluginOrGrailsScript(GrailsScriptRunner.java:383)
 at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeCommand(GrailsScriptRunner.java:362)
 at org.codehaus.groovy.grails.cli.GrailsScriptRunner.main(GrailsScriptRunner.java:228)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.codehaus.groovy.grails.cli.support.GrailsStarter.rootLoader(GrailsStarter.java:234)
 at org.codehaus.groovy.grails.cli.support.GrailsStarter.main(GrailsStarter.java:262)
Caused by: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\GrailsReverseEngineeringStrategy.groovy: 19: unable to resolve class org.apache.log4j.Logger
 @ line 19, column 1.
   import org.apache.log4j.Logger
   ^
C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\GrailsTemplateProducer.groovy: 17: unable to resolve class org.apache.log4j.Logger
 @ line 17, column 1.
   import org.apache.log4j.Logger
   ^
C:\Users\fourgablesguy\.grails\2.0.4\projects\fourgablesguy\plugins\db-reverse-engineer-0.4\src\groovy\grails\plugin\reveng\ReverseEngineerProgressListener.groovy: 17: unable to resolve class org.apache.log4j.Logger
 @ line 17, column 1.
   import org.apache.log4j.Logger
   ^
3 errors
 at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:302)
 at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:858)
 at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:548)
 at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:497)
 at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:480)
 at org.codehaus.groovy.tools.FileSystemCompiler.compile(FileSystemCompiler.java:60)
 at org.codehaus.groovy.tools.FileSystemCompiler.doCompilation(FileSystemCompiler.java:216)
 at org.codehaus.groovy.ant.Groovyc.compile(Groovyc.java:909)
 ... 200 more
| Error Error executing script DbReverseEngineer: : Compilation Failed
This line indicated that my jar for log4j was corrupt?
[groovyc] java.util.zip.ZipException: invalid CEN header (bad signature)
I redownloaded that jar from an internet repository and replace my local copy and reran the command got this instead
Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContextAware
 at java.lang.ClassLoader.defineClass1(Native Method)
 at java.lang.ClassLoader.defineClassCond(Unknown Source)
 at java.lang.ClassLoader.defineClass(Unknown Source)
 at java.security.SecureClassLoader.defineClass(Unknown Source)
 at java.net.URLClassLoader.defineClass(Unknown Source)
 at java.net.URLClassLoader.access$000(Unknown Source)
 at java.net.URLClassLoader$1.run(Unknown Source)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(Unknown Source)
 at java.lang.ClassLoader.loadClass(Unknown Source)
 at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
 at java.lang.ClassLoader.loadClass(Unknown Source)
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Unknown Source)
 at grails.plugin.reveng.Reenigne.class$(Reenigne.groovy)
 at grails.plugin.reveng.Reenigne.$get$$class$grails$util$GrailsUtil(Reenigne.groovy)
 at grails.plugin.reveng.Reenigne.execute(Reenigne.groovy:73)
 at grails.plugin.reveng.Reenigne$execute.call(Unknown Source)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
 at grails.plugin.reveng.RevengRunner.run(RevengRunner.groovy:81)
 at grails.plugin.reveng.RevengRunner$run.call(Unknown Source)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
 at grails.plugin.reveng.RevengRunner.main(RevengRunner.groovy:28)
Caused by: java.lang.ClassNotFoundException: org.springframework.context.ApplicationContextAware
 at java.net.URLClassLoader$1.run(Unknown Source)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(Unknown Source)
 at java.lang.ClassLoader.loadClass(Unknown Source)
 at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
 at java.lang.ClassLoader.loadClass(Unknown Source)
 ... 27 more
This is due to grails 2.0 being incompatible with db-reverse-engineer plugin, so I downloaded grails 1.3.7 and created a dummy project for that version of grails, installed the db-reverse-engineering plugin 0.3 and ran it successfully from that grails version.
cd C:\dev\
C:\tools\grails-1.3.7\bin\grails create-app dbreveng
cd dbreveng
C:\tools\grails-1.3.7\bin\grails interactive
install-plugin db-reverse-engineer 0.3
integrate-with --eclipse
Import project into SpringSource Tool Suite, you will have to configure STS to be Grails 1.3.7 aware using the dialogs that appear. Using an editor in STS: edit the grails-app/Config.groovy, grails-app/DataSource.groovy with actual database connection. Copy your database jdbc jar into dbreveng/lib you cannot use the 0.4 configuration option
//this does not work on 0.3 version, instead copy your jdbc jar to the project lib 
grails.plugin.reveng.jdbcDriverJarDep = 'com.oracle:ojdbc5:11.2.0.2.0'
db-reverse-engineer --verbose

Welcome to Grails 1.3.7 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: C:\Tools\grails-1.3.7\

Base Directory: C:\DEV\sbpsdbreveng
* FOURGABLES_REPOSITORY=C:/fourgablesguy
WARNING: Configurational method [checksums] in grails-app/conf/BuildConfig.groovy doesn't exist. Ignoring..
WARNING: Configurational method [inherits] in grails-app/conf/BuildConfig.groovy doesn't exist. Ignoring..
Resolving dependencies...
Dependencies resolved in 858ms.
Running script C:\Users\fourgablesguy\.grails\1.3.7\projects\sbpsdbreveng\plugins\db-reverse-engineer-0.3\scripts\DbReverseEngineer.groovy
Environment set to development
  [groovyc] Compiling 3 source files to C:\DEV\sbpsdbreveng\target\classes
  [groovyc] Compiling 1 source file to C:\DEV\sbpsdbreveng\target\classes
     [echo] Starting database reverse engineering, connecting to 'jdbc:oracle:thin:@hostname:1521:sid' as 'USERNAME' ...
     [echo] Finished database reverse engineering
Here are my configs for reverse engineering from Oracle 10 db..
grails-app/Config.groovy
grails.plugin.reveng.packageName = 'com.fundtech.sbps.db'
//grails.plugin.reveng.manyToManyBelongsTos = [] 
//grails.plugin.reveng.versionColumns = ''
grails.plugin.reveng.defaultSchema = 'USERNAME'
grails.plugin.reveng.includeTables = ['CUSTOMER']

grails-app/DataSource.groovy
dataSource {
 dbCreate = "create"
 url = "jdbc:oracle:thin:@hostname:1521:sid"
 username = "USERNAME"
 password = "password"
 dialect = org.hibernate.dialect.Oracle10gDialect.class
 properties {
  maxActive = 1000
  maxWait = 5000
  maxIdle = 2
  driverClassName = "oracle.jdbc.OracleDriver"
  validationQuery="SELECT 1 from DUAL"
 }
 loggingSql = true
}

Wednesday, July 11, 2012

How to add external jar libraries to your Grails 2.0

I needed to setup my Grails application with a custom library that was not provided by traditional maven public repositories. Here is how I got it working:
1. Setup a local folder structure to hold custom libraries using maven/ivy naming convention. Add a system environment variable for the path to the local folder
2. Edit grails-app/conf/BuildConfig.groovy to add the local repository.
3. Edit grails-app/conf/BuildConfig.groovy to add the new local dependency jar.
4. Test the build by running grails command dependency-report
5. Create a new build with grails command war
6. Regenerate the Spring Source Tool Suite project and classpath files using grails command integrate-with --eclipse

Listing for step 1 Local Repository
C:.
├───lib
│   └───com
│       └───fourgablesguy
│           └───myapplication
│               └───1.0.0
│                   └───myapplication-1.0.0.jar

set LOCAL_REPOSITORY=C:\lib
Listing for step 2 and 3 BuildConfig.groovy
if (System.getenv().LOCAL_REPOSITORY == null) {
 println "*"
 println "* ERROR - LOCAL_REPOSITORY environment variable is undefined."
        System.exit(1)
} else {
 println "* LOCAL_REPOSITORY=" + System.getenv().LOCAL_REPOSITORY
 localRepoDir = System.getenv().LOCAL_REPOSITORY
}
grails.project.dependency.resolution = {
    //snip 
    repositories {
        //snip 
 mavenRepo "file:${localRepoDir}"
    }
    dependencies {
        //snip 
        compile "com.fourgablesguy:myapplication:1.0.0"
    }
}
Listing for step 4-6 Grails commands
grails dependency-report 
grails package
grails integrate-with --eclipse

Friday, July 6, 2012

How to set Grails 2.0 DataSource to use JNDI for run-app command.

I wanted to setup my Grails 2.0 application to use a JNDI connection in the DataSource.groovy file. Here is how I got it working:

  1. Edit grails-app/conf/DataSource.groovy and configure a jndi data source:
  2. Edit grails-app/conf/Config.groovy and configure the Grails managed resource
  3. Edit the BuildConfig.groovy to insert the resource-ref in the web.xml
Here is the listing for DataSource.groovy:

environments {
    development {
dataSource {
dbCreate = "create"
jndiName = 'java:comp/env/jdbc/mydatasource'
}
              } 
}
Here is the listing for Config.groovy:

environments {
    development {
        grails.logging.jul.usebridge = true
jquery.minified = true
jqueryUi.minified = true
grails.naming.entries = ['jdbc/mydatasource': [
type: "javax.sql.DataSource",
       auth: "Container",
       description: "Data source for ...",
url: "jdbc:oracle:thin:@:",
username: "",
password: "",
driverClassName: "oracle.jdbc.driver.OracleDriver",
maxActive: "8",
              maxIdle: "4"
]
]
      }
}
Note: You will need to manually add postgres, mysql, oracle or db2 jdbc jar(s) to the application lib folder to use a datasource which references a driverClassName which is not provided by the Grails platform by default. 

Here is the listing for BuildConfig.groovy :


grails.war.resources = { stagingDir, args ->
def webxml = new File(grailsSettings.baseDir,"${stagingDir}/WEB-INF/web.xml")
def newxml = new File(grailsSettings.baseDir,"${stagingDir}/WEB-INF/new.xml")
def root = new XmlParser().parse(webxml)


// add the jdbc/mydatasource resource reference to the web.xml
def resourceRef = root.appendNode('resource-ref')
resourceRef.appendNode('description','The JNDI Database resource')
resourceRef.appendNode('res-ref-name','jdbc/mydatasource')
resourceRef.appendNode('res-type','javax.sql.DataSource')
resourceRef.appendNode('res-auth','Application')

def writer = new StringWriter()
new XmlNodePrinter(new PrintWriter(writer)).print(root)
newxml.withWriter { out ->
out.writeLine(writer.toString())
}
webxml.delete()
newxml.renameTo(webxml.path)
}

The code in BuildConfig is only needed to ensure the deployed war file has the required resource references. I do not believe you need that for just using the grails run-app command.




Wednesday, June 27, 2012

How do I set a new version for my existing Grails application?


I have been working with Grails lately for a new web project. So far it has been hard, but a lot of fun. I am new to Groovy as well. But I do have experience with Spring and Hibernate, which the application framework is built on top of. I found a JIRA issue which matched an error I was seeing in my code.

I am using Spring Source Tool Suite (STS) to develop the application and, by default, new projects are set with a version of Grails preinstalled by the Grails plugin, in my case it was at version 2.0.3. The fix I need is in version 2.0.4. This brought me to a question: How do I switch to a newer version of Grails or backport a fix to my version? The Grails documentation is quite extensive but I did not find a command to do this. This command:
grails set-version 2.0.4

| Loading Grails 2.0.3
| Configuring classpath.
| Environment set to development.....
| Application version updated to 2.0.4

Only sets your application's declared version, not the version of grails used to build and run your application.

Under the covers, this command is simply modifying the application.properties file and setting the property named app.version to the value you specify.

This same file has a property named app.grails.version, my app has this set to:
app.grails.version=2.0.3
Changing that value to 2.0.4, will not change what version of Grails you application is built with in STS, but I changed the value to 2.0.4 anyway. To get on 2.0.4 and resolve my issue I needed to first download the version of Grails I want to switch to. Extract the download to a file location on my system. Then in STS, I added the new version to the Grails plugin and set it as the default version. This is done using Window | Preferences | Groovy | Grails | Add. Finally in STS, use the grails command prompt (ctrl+alt+shift+g) to run

grails clean
| Loading Grails 2.0.4
| Configuring classpath.
| Environment set to development.....
| Application cleaned.

I am now  able to run my  application, all the classes are compiled with the new Grails version and the project is upgraded.


| Loading Grails 2.0.4
| Configuring classpath.
| Environment set to test.....
| Compiling 1 source files.....
| Compiling 50 source files.
| Running 2 unit tests... 1 of 2
| Running 2 unit tests... 2 of 2
| Completed 2 unit tests, 0 failed in 13013ms
| Tests PASSED - view reports in target\test-reports
I am still not sure about the process to backport JIRA fixes as patches to an older version, but this solution is sufficient for me for the current state of my project. Maybe I will post a question to stackoverflow about porting fixes to older versions.


If you are starting a Grails project, be sure to bookmark the Groovy, Grails, Spring, Hibernate, forums and  JIRA sites. Be aware of what versions of these technologies your project is running so you can intelligently find and resolve problems.


Tuesday, April 3, 2012

NClass - Free UML Class Designer



If you are ever looking for a nice UML class designer look no further than NClass. I used this for a project to port a large code base from .NET to Java. The program was able to reverse engineer UML from compiled .NET code. Love it.

Thursday, March 29, 2012

A Spiritual Feast

I am excited for the 2012 LDS spring conference sessions.

Come listen to living prophets


Come listen to living prophets

You can listen or watch them for free online. Consider accepting my invitation to attend conference and pull up your own chair to a spiritual feast.

Friday, March 23, 2012

Performance settings for production weblogic deployments

Put this in the weblogic.xml under WEB-INF folder: 
<!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application 8.1//EN" "http://www.oracle.com/technology/weblogic/servers/wls810/dtd/weblogic810-web-jar.dtd">

<weblogic-web-app>

<container-descriptor>
<servlet-reload-check-secs>-1</servlet-reload-check-secs>
</container-descriptor>

</weblogic-web-app>

For JSPs you can also set this in weblogic.xml:

<jsp-descriptor>
<jsp-param>
<param-name>pageCheckSeconds</param-name>
<param-value>-1</param-value>
</jsp-param>
</jsp-descriptor>


Unless you are altering servlet code and JSPs on the fly in production (bad idea), there is no need to ever check for changes. These two settings can help with performance because without them, Weblogic will have periodic threads blocking
requests to poll the filesystem for Servlet or JSP changes.

So by default in thread dumps you will see one or more of this sort of thing:

waiting for monitor entry [c4f7f000..c4f7fc28]
     at weblogic.servlet.internal.ServletStubImpl.checkForReload(ServletStubImpl.java:771)

unless you disable that like shown above.

Monday, March 5, 2012

8 reasons why your browser does NOT send the cookie as part of the request

There are several reasons why a cookie you attempted to set on a remote client browser as part of a HTTP response is NOT sent back on the next request:
  1. The domain of the request does not match the cookie's domain attribute
  2. The path of the request does not match the cookie's path attribute
  3. The cookie has expired
  4. The cookie was set the secure attribute and the client's request was plain text HTTP.
  5. The cookie was set with the httpOnly attribute and the client's request was not HTTP/HTTPS (e.g. you used FTP).
  6. The client has disabled cookies globally or specifically for your domain.
  7. The client deleted or cleared the cookie that was set before the next request was made.
  8. The client's browser does not trust the SSL certificate used to sign your site and you are trying to use HTTPS communication.
Your domain of the request does not match the cookie's domain attribute
This one appears to be the most obvious of them all but does have a small gotcha. A cookie set for domain www.google.com will not be sent for a request to www.yahoo.com. We can understand that, but it will also not be sent for mail.google.com! The domain mail.google.com does not match www.google.com, so cookies set on one do not affect requests for the other. So when setting cookies that should be sent for all sub-domains: use .domain.com as the cookie's domain attribute, i.e. leave off the sub-domain (www) and just lead with the . prefix.

Your path of the request does not match the cookie's path attribute
If you set the path to /, all paths on the domain are going to send the cookie with the request, even if the request is for an image.. So use path wisely to avoid unnecessary overhead in your requests, especially if you are a heavy user of cookies. you only get one cookie path, make it count. You will be ding'd on Yslow if you don't avoid sending cookie info for images.

Your cookie has expired
Duh. Don't expect old cookies to join your request party. Be careful of short expiration on cookies, they may go stale before they are even set.

Your client has disabled cookies globally or for your specific domain
This is why it is important to document the requirements for your application. If you need cookies enabled (or even better detect that cookies are not enabled), tell the user to enable them (and how to enabled them) in a big red alert box with a flashing siren.


This is my list, do you have other reasons to add?





Thursday, February 16, 2012

Java little endian IO gotcha

Java's goal has been to provide developers with a language that is cross platform, write once run everywhere. To do this Java handles many platform details for you. But sometimes those details are important. Here is an example, I needed to output a TIFF using little-endian byte ordering regardless of what platform the Java code was running on.

import java.io.FileOutputStream;

byte[] imgData = //create the image data using JAI;
String filename = "platform-endian.tiff";

FileOutputStream fos = new FileOutputStream(filename);
fos.write(imgData);
fos.close();

My code would work fine on platforms with Intel or x86 architecture which is little-endian byte order, but when I moved my code to a Solaris system running a SPARC processor, my code started outputting in big-endian TIFFs. This is due to the fact that FileOutputStream hides some of the complexity involved with writing data out to disk. Hiding this complexity is fantastic if all you care about are outputting TIFFs that are byte-order-compatible with the environment your Java code is running in; which is what you would want in 99% of the use cases for creating TIFFs programmatically. But this feature of Java is very bad when you always need little-endian TIFFs at all times. I need little-endian because it is a Federal Reserve regulations are that the TIFFs I make be little-endian.

Thankfully there is a way to force Java to use a specific byte ordering. Use ByteBuffer.

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.io.FileOutputStream;

byte[] imgData = //create the image data using JAI;
String filename = "little-endian.tiff";

ByteBuffer buffer = ByteBuffer.allocate(imgData.length);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.put(imgData);
out = new FileOutputStream(filename).getChannel();
out.write(buffer);

This code will output directly in little-endian regardless of the architecture of the system running the code.


Thursday, January 26, 2012

Java static initialization gotcha

If you have a class which has a singleton instance of itself as a static member, and also use a static inititialization block, then you can run into an issue with initialization like I did where static final members are null.
01 import java.util.*;
02
03 class MySingletonClass {
04 private static final instance = new MySingletonClass();
05 private static final List MY_STRINGS;
06 static {
07 MY_STRINGS = new ArrayList();
08 }
09 public MySingletonClass() {
10 System.out.println("MY_STRINGS: "+MYSTRINGS);
11 }
12 }

The above will throw a NullPointer Exception on line 10 because the MySingletonClass constructor is called BEFORE the static initialization block is executed. So change it to this:
01 import java.util.*;
02
03 class MySingletonClass {
04 private static final instance;
05 private static final List MY_STRINGS;
06 static {
07 MY_STRINGS = new ArrayList();
08 instance = new MySingletonClass();
09 }
10 public MySingletonClass() {
11 System.out.println("MY_STRINGS: "+MYSTRINGS);
12 }
13 }

Now the instance static member variable is not created until AFTER the other static member is initialized. So the constructor can correctly execute the print statement.

Tuesday, January 24, 2012

Use package-info.java for all your package level annotation needs

I had a problem, I needed to annotate all the occurrences of java.sql.Timestamp with an XmlJavaTypeAdapter for all classes in a Java package. For example I needed this done in dozens of generated source files:

@XmlJavaTypeAdapter(com.fourgablesguy.dao.hibernate.util.TimestampAdapter.class)
public Timestamp getCreateTs() {
return this.createTs;
}

The TimestampAdapter class is the following:
package com.fourgablesguy.dao.hibernate.util;

import java.sql.Timestamp;
import java.util.Date;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class TimestampAdapter extends XmlAdapter {

@Override
public Date marshal(Timestamp v) throws Exception {
return new Date(v.getTime());
}

@Override
public Timestamp unmarshal(Date v) throws Exception {
return new Timestamp(v.getTime());
}

}


The reason I needed this done is because Timestamp does not have a public no-arg constructor and XStream could not marshall objects containing Timestamp objects. The nice solution to annotating these is to use package-info.java, you place this file in the same folder as the source java files, but it is not a typical source file. Here is the contents of my package-info.java:
@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters
({
@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(value=com.fourgablesguy.dao.hibernate.util.TimestampAdapter.class,type=java.sql.Timestamp.class)
})
package com.myama.dao.hibernate;

This package-info file is used by Java to annotate all classes in a package, with this single file my problem was resolved. My TimestampAdapter allowed me to marshall Timestamp objects with XStream. I used fully qualified names of classes in the package-info since I was not clear if you could import packages or if you had package access to the enclosing namespace.

Wednesday, January 18, 2012

Keep your browser updated

Financial and Health industries are notorious for being slow to adopt better technology and instead cling to inferior hardware/software beyond the logical pain point, web browsers included. As a general philosophy I recommend it would be healthy for these industries to adopt the policy that web browsers be kept updated and applications used by the company be maintained to work correctly with modern browsers.

Here are three good reasons to keep browsers updated:
First, old browsers (and the OS they run on) are vulnerable to attacks.
Second, the web evolves quickly. Old browsers will miss out.
Third, old browsers slow down innovation on the web.

I worked with a previous client who insisted on a dynamic Web 2.0 look to the complex web application I was designing but also demanded compatibility with IE7. Delivering on both of these requirements (latest Internet bells and whistles, like mobile browser compatibility and AJAX, as well as backward compatibility with older browser versions) increases the difficulty level and cost of the site development considerably for a number of reasons:
  • First you have to test on these older browser versions in addition to testing on the common browsers, which increases the development time. It is not just twice the work, because you have to worry about supporting all browsers with a single application, making a single change requires testing all browsers to make sure fixing an issue in one browser does not break something in another.
  • Next you have to pare down features and functionality so that it works consistently everywhere, so you might have had a nice dynamic form element or navigation control working in IE9 and FireFox 4, but it all gets tossed out when it cannot work in IE7 (see holding up innovation reason given above).
  • Also, for some "must have" site features or functionality: developers will usually have to code around older browser version quirks, so instead of writing code in one place to perform a task, it is written one place or one way for modern browsers and another place or another way for older browsers (see slowing down the web). This causes a code maintenance issue as you now have multiple places to check to fix problems or update code for a single feature or site behavior. This is a problem for HTML, CSS, and Javascript as all three can behave differently on different browsers.
  • Yet another problem that can arise is your Javascript/CSS performance can vary widely in different browser flavors and versions, for example IE7 Javascript benchmarks are miserably slow when compared with more recent versions of IE and other browsers like FireFox or Chrome. This can cause problems where failing to test on the required browser versions can really bite you.
  • If a performance issue (or any browser version issue) is found late in the development cycle, either because the testing was not done along side development in that version or because developers only used modern browsers for their self verification and validation of the application, then the time needed to fix the entire problem is much larger and more difficult than if it had been caught earlier because much more code is in place to review and repair and test.

99% of businesses do not have the resources to provide application support on dozens of browsers versions, it is less expensive to support the current browsers than to support historical ones. Developers are much happier working with current tech than outdated tech as well. Your clients may not want to upgrade their browsers, they may ‘need’ the old browser to access a neglected internal application which only works with a specific legacy browser, but clients refusing to update their software and maintain their web applications are hurting themselves (and you) in several ways:
  1. old software makes their business less competitive (faster browsers/computers make a more efficient workforce);
  2. old/inferior software has high hidden costs (performance issues, functional issues, security vulnerabilities, feature limitations, and incompatibilities with emerging technologies);
  3. outsourced development vendors always find doing business with clients clinging to old software is more expensive and they increase their bids accordingly (I saw this first hand many times working as a consultant);
  4. some development vendors even flat out refuse business which requires older browser compatibility as a policy / business strategy. This allows their developers freedom to ignore issues only present in older browsers and they can therefore innovate more efficiently.
Newer IE browsers can run in a legacy mode, emulating the previous versions, for those rare cases where a legacy browser mode is needed to use a web site. You can even set preferences for specific sites such that certain sites always use a compatibility mode. The barrier to upgrading to a new browser is mostly self-inflicted because browser creators do everything possible to encourage adoption of the newer version.

Tuesday, January 17, 2012

How do I test my web application against IE6 and IE7 in Windows 7?

How do I test my web application against IE6 and IE7 and IE8 and IE9 in Windows 7?

Problem: Windows 7 comes with IE8 or IE9 or IE10 (and does not have a path back to use IE6 or IE7, (and don't patronize me with browser emulation solutions, they all suck.) Microsoft has sunsetted support for IE6 and IE7 is getting closer to being out of support as well.

Solution:

Go here http://www.microsoft.com/windows/virtual-pc/download.aspx

  1. Download the 500 MB Windows XP Mode VHD installer.
  2. Run the installer.
  3. Download Virtual PC if you lack this.
  4. Test with IE6 bundled in the vhd.
  5. Make a second vhd and upgrade to IE7 within the Virtual PC VM.*
  6. Rinse and repeat for IE8, IE9
  7. If you are doing local web development, install the Microsoft Loopback adapter on your host OS.
  8. You now have the ability to test your site in native IE6 and IE7 and IE8, IE9, and IE10.

Other tools exist to emulate or simulate IE6 and IE7 web rendering, but they will always fall short of the mark and open you to risks if they fail to display your site *exactly* the way it displays in the native browser and I recommend that they should not be used for any project where you can use a VM instead.

*For this step there are some special tricks to it. After making a copy of your IE6 vhd file, you need to change it's hardware signature to avoid conflicts with running it in parallel with your IE6 VM.

Windows 7 comes with a command line utility called diskpart that can let you view and change the disk signature.


Open a command prompt as administrator. To do this in Windows 7, click the Windows start menu (the round Windows icon on the left bottom corner), type "cmd" (without the quotes), right click the "cmd.exe" item that appears at the top of your menu, and click the line "Run as administrator". Do this even if you are already logged in as administrator, since on Windows 7, administrators run with reduced rights by default.


A black command prompt window will open. In Windows 7, the title bar of the window will tell you that you are running it as Administrator. If it does not, it means you did not do what I just said above. Return and follow the first step, or you will not be able to successfully carry out the rest of this tutorial.


Type "diskpart" (without the quotes) into the window. (Note: for this and the other commands described here, you'll have to hit the ENTER key after you finish typing your commands for them to take effect.)


Microsoft DiskPart will start. When it is ready, it will issue a "DISKPART>" prompt, allowing you to enter your commands.


Type "list disk" (without the quotes). This will list all the disks that are currently mounted (connected to the system). The disk will not have the usual names and labels that you're accustomed to from the Windows Explorer interface, so you will have to recognize them by their sizes.


Note that "list disk" actually lists the physical disks, and not the partitions that you may have assigned drive letters. This means that if you have 2 physical disks, with 3 partitions on each, so that you have drives C:, D:, E:, F:, G: and H:, "list disk" will only show "Disk 0" and "Disk 1".


To view the signature of a disk, you must first select it. To select a disk, type "select disk x" (without the quotes) where x is the number of the disk from your "list disk" display. When you type (say) "select disk 1", DiskPart will respond by telling you "Disk 1 is now the selected disk".


Now type "uniqueid disk" (again, without the quotes). DiskPart will respond with the disk's signature, a series of hexadecimal digits (or at least I think it's hexadecimal).


To change the signature to some other number, type "uniqueid disk ID=[NEW SIGNATURE]" (without the quotes) where "[NEW SIGNATURE]" stands for the new identifier you want for the disk (without the square brackets and without the quotes). However, before you do that, you may want to type "help uniqueid disk", which will give you more information on how the command works. You may also want to find out the disk signatures of your other disks on your system before you modify your current one so that you don't cause a new signature collision in trying to solve your current problem. In addition, if you're really not sure how many digits you should give your disk, perhaps try changing only one digit of the current signature (eg, increasing or decreasing it by 1). Remember my disclaimer above: I really don't know what I'm talking about here: do it at your own risk.


To quit DiskPart, type "exit". Incidentally, in case you get lost while running DiskPart, when you are at the "DISKPART>" prompt, you can type "help" to get a list of commands. Typing "help" followed by the command typically gives you more info about that command.


Once you've quit DiskPart, type "exit" again to quit the Administrator Command Prompt


About Me

My photo
Lead Java Developer Husband and Father

Tags