Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

When writing a script, it may be unwieldy to call the script defining the whole classpath at the command line, e.g.

groovy -cp %JAXB_HOME%\bin\activation.jar;%JAXB_HOME%\bin\... myscript.groovy

You can go the other way - let the script itself find the jars it needs and add them to the classpath before using them. To do this, you need to

1. get the groovy rootloader

def loader = this.class.classLoader.rootLoader

2. introduce the necessary uls to groovy rootloader. Use whatever logic suits your situations to find the jars / class directories

Code Block
def jardir = new File( System.getenv( 'JAXB_HOME' ), 'lib' )
def jars   = jardir.listFiles().findAll { it.name.endsWith('.jar') } 
jars.each { loader.addURL(it.toURI().toURL()) }

3. Load the classes you need:

Code Block
// in a script run from command line this is ok:
JAXBContext = Class.forName( 'javax.xml.bind.JAXBContext' )
Marshaller  = Class.forName( 'javax.xml.bind.Marshaller' )

// if the groovy script / class is loaded from a java app, then the above may fail as it uses the same classloader to load the class as the containing script / class was loaded by. In that case, this should work:

JAXBContext = Class.forName( 'javax.xml.bind.JAXBContext', true, loader )
Marshaller  = Class.forName( 'javax.xml.bind.Marshaller', true, loader )

4. To instantiate the classes, use the newInstance method:

Code Block
def jaxbContext = JAXBContext.newInstance( MyDataClass )

Note that newInstance is on steroids when called from groovy. In addition to being able to call the parameterless constructor (as w/ Java's Class.newInstance()), you can give any parameters to invoke any constructor, e.g.

Code Block
def i = MyClass.newInstance( "Foo", 12 ) // invokes the constructor w/ String and int as params

You can also pass a map to initialize properties, e.g.

Code Block
def i2 = MyClass.newInstance(foo:'bar', boo:12) // creates a new instance using the parameterless constructor and then sets property foo to 'bar' and property boo to 12

The downside of using this approach is that you can't inherit from the classes you load this way - classes inherited from need to be known before the script starts to run.