Thursday, April 26, 2012

ANT: how to load library on the fly (at the runtime)

This post was caused by the try to use sshexec ant command in my build scenario. However the regular ant distribution does not contain the classes supporting functionality for that task. So the simplest but not flexible way is to get the corresponding jar file and put it under ANT_HOME/lib. Otherwise you will get the message like this
Problem: failed to create task or type sshexec
Cause: Could not load a dependent class com/jcraft/jsch/Logger
       It is not enough to have Ant's optional JARs
       you need the JAR files that the optional tasks depend upon.
       Ant's optional task dependencies are listed in the manual.
Action: Determine what extra JAR files are needed, and place them in one of:
        -D:\apache-ant-1.8.3\lib
        -C:\Users\username\.ant\lib
        -a directory added on the command line with the -lib argument
But if there is a way to attach the library in a runtime? Yep, such the way exists. So you have to do the following:
1. Download the ant-classloadertask.jar and place it where the resources of your build procedure reside
2. Download jsch-0.1.47.jar that supports ssh communication used by sshexec task
3. Use the following pattern in your ant scenario


<target name="execute-ssh-command">

 <property name="jarfolder" value="D:/resources/jars"/>
 <property name="ssh.support" value="jsch-0.1.47.jar"/>
 <property name="custom.class.loader" value="ant-classloadertask.jar"/>

 <!-- Define task for new classloader -->
 <taskdef resource="net/jtools/classloadertask/antlib.xml" classpath="${jarfolder}/${custom.class.loader}"/>
 
 <!-- Load the required jar -->
 <classloader loader="system" classpath="${jarfolder}/${ssh.support}"/>

 <property name="command.input">
 <!--
  Some input for ssh command here
 -->
 </property>
 
 <sshexec host="YOUR_HOST" username="YOUR_USERNAME" command="YOUR_COMMAND" inputproperty="command.input"/>
 
</target>