CustomSQLChange and ClassNotFoundException


I am having problems using a CustomChange.  I have created a class, MyCustomChange, which implements CustomSQLChange and compiled it.


When I try to run the update via ant, I get the following exception

    liquibase.exception.CustomChangeException: java.lang.ClassNotFoundException: com.example.MyCustomChange

Earlier in the ant file, I set my base.classpath to the lib directory which contains hibernate.jar, all the database drivers and liquibase. 
The updateDatabase depends on compile, which compiles my custom change and places it in ${basedir}/foo/bin.  I have verified that the compiled class file is present.  In the updateDatase, I set my classpath composed of the base.classpath and ${basedir}/foo/bin.  The classpath is printed out and contains ${basedir}/foo/bin.

    	<path id="classpath">
    		<pathelement location="${basedir}/foo/bin"/>
    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <path refid="base.classpath"/>
    	<property name="cp" refid="classpath"/>
    	<echo message="cp=${cp}"/>
    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; changeLogFile="${db.changelog.file}"
    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; driver="${database.driver}"
    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url="${url}"
    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; username="${username}"
    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; password="${password}"
    		&nbsp; &nbsp; defaultSchemaName="${}"
    		&nbsp; &nbsp; classpathref="classpath">
    		&nbsp;  <changeLogProperty name="db.path" value="${db.path}"/>
    		&nbsp;  <changeLogProperty name="database.type" value="${database.type}"/>
    		&nbsp;  <changeLogProperty name="hibernate.username" value="${username}"/>
    		&nbsp;  <changeLogProperty name="hibernate.password" value="${password}"/>
    		&nbsp;  <changeLogProperty name="liquibase.dir" value="${liquibase.dir}"/>

When liquibase runs, I get the exception.  The exception is originating in CustomChangeWrapper.setClass.

I have tried creating a jar file from the class file and using that in the classpath instead.  Same results. 

Any idea on why liquibase is unable to load the custom class?  This is with the latest liquibase from the trunk. 


That should work.  I’ll look into it.



I did a little bit of debugging in CustomChangeWrapper.setClass.

        public void setClass(String className) throws CustomChangeException {         ....         try {             try {                 Object o =  Class.forName(className, true, classLoader).newInstance();                 System.out.println("*** o = " + o.toString());                 System.out.println("***class = " + o.getClass().getCanonicalName());                                 System.out.println("o is an instance of CustomSqlChange: " + CustomSqlChange.class.isInstance(o));                 System.out.println("o is an instance of CustomChange: " + CustomChange.class.isInstance(o));                 customChange = (CustomChange)o;             } catch (ClassCastException e) { //fails in Ant in particular             ...

When I recompile and run this updated jar, my output is:

    [updateDatabase] *** o = com.example.MyExample@3f6843 [updateDatabase] ***class = com.example.MyExample [updateDatabase] o is an instance of CustomSqlChange: false [updateDatabase] o is an instance of CustomChange: false

So the first Class.forName actually loads something that is of the correct class.  Yet for some bizarre reason it doesn’t think it is an instance of CustomSQLChange or its parent CustomChange.  Thus the class cast exception, which forces it to try the other two methods of loading the class.  Neither of those are able to load it,  resulting in the ClassNotFoundException.

This is weird, because if I add a little reflection code to see the interfaces on o, it returns CustomSqlChange.  Which is correct, it does implement CustomSqlChange.


Hi again,

I think I found a possible work around. I know my team mates are not going to like it though. 

Running ant with the “-lib” option, such as

ant -lib c:/dir/where/liqubase.jar/is/located redoDB

produces the following debugging output:

    [updateDatabase] ***class = com.example.MyExample [updateDatabase] o is an instance of CustomSqlChange: true [updateDatabase] o is an instance of CustomChange: true

So it seems like some issue where ant classloader doesn’t find the liquibase.jar.  It is part of my classpath defined in ant though. 


Glad you found a work-around.  I’ll get it fixed for 2.0 final.



I’m using 2.01 and still getting this problem. Any ideas?

Do you have a full stacktrace you get?



    I’m using 2.0 and it looks like I’ve also hit this problem when trying to use custom change (and in trying to resolve the issue all my searching has brought me here !). I’ve created a class called ‘Show’  which implements CustomSqlChange and compiled it.  My liquibase changeset is as follows :-




When I run liquibase (directly , not via ANT) I get :-


INFO 03/04/13 10:03:liquibase: Successfully released change log lock
Liquibase Update Failed: java.lang.ClassNotFoundException: Show
SEVERE 03/04/13 10:03:liquibase: java.lang.ClassNotFoundException: Show
liquibase.exception.ChangeLogParseException: Invalid Migration File: java.lang.C
lassNotFoundException: Show
        at liquibase.parser.core.xml.XMLChangeLogSAXParser.parse(XMLChangeLogSAX
        at liquibase.parser.core.xml.XMLChangeLogSAXHandler.handleIncludedChange
        at liquibase.parser.core.xml.XMLChangeLogSAXHandler.startElement(XMLChan
ment(Unknown Source)
emptyElement(Unknown Source)
ement(Unknown Source)
StartElement(Unknown Source)
l$ Source)
nknown Source)
(Unknown Source)
l.scanDocument(Unknown Source)
nknown Source)
nknown Source)
        at So
known Source)
arse(Unknown Source)
        at liquibase.parser.core.xml.XMLChangeLogSAXParser.parse(XMLChangeLogSAX
        at liquibase.Liquibase.update(
        at liquibase.integration.commandline.Main.doMigration(
        at liquibase.integration.commandline.Main.main(
Caused by: org.xml.sax.SAXException: java.lang.ClassNotFoundException: Show
liquibase.exception.CustomChangeException: java.lang.ClassNotFoundException: Show


Any advice on how to resolve this would be appreciated.