Using LiquiBase directly from Java

I want to be able to call the LiquiBase directly from Java and go to all the trouble of calling it from command line via JNI or to call it via the main(String[] args) method. Is there a way (and a howto/example)
Thanks in advance
Orlin

Hi Orlin,
Yes you can call perfectly liquibase directly in your code.
As example you can look at the integration test sourcecode. Look at class liquibase.dbtest.AbstractIntegrationTest

You could also look at http://liquibase.jira.com/source/browse/~raw,r=1461/CORE/trunk/liquibase-core-jvm/src/main/java/liquibase/integration/spring/SpringLiquibase.java, in particular the afterPropertiesSet method.

It basically comes down to:

Liquibase liquibase = new Liquibase(changeLog, resourceOpener, connection)
liquibase.update(getContexts());

Nathan

Thanks,
I will it tomorrow.

Ok,
so I tried but unfortunatly I have the following problem - in the SpringLiquibase there is the following line:
Database database =
                    DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(dataSource.getConnection()));
which I cannot recreate since I just don’t have liquibase.database.JdbcConnection.
I am using maven:
http://mvnrepository.com/artifact/org.liquibase/liquibase-core/1.9.5
So, what to do?

I would suppose that this is a convinence method which them initializes the needed connection:
http://www.liquibase.org/api/liquibase/database/Database.html
Like for example choosing mysql or mssql…

Anyway, as always I would appreciate any help.

Cheers,
Orlin

Yes, trunk has been heavily refactored for the upcoming 2.0 release.  Sorry.  Take a look at http://liquibase.jira.com/source/browse/~raw,r=750/CORE/trunk/core/src/java/liquibase/spring/SpringLiquibase.java

Nathan

I am currently migrating from 1.9.5 to 2.0 RC2.  The code loads the JTDS driver using DriverManager and then passed in the java.sql.Connection to the constructor of Liquibase.

In 2.0 the API has changes and its not clear to me how I can go about doing it as it seems to rely on internal Liquibase Database classes for each type of database.

Nathan, do you maybe have a sample on how to use a driver like JTDS with the 2.0 API?

The job of the Database classes is to support all the database-type specific logic (which support deferrable foreign key constraints, etc).  Whether you use JTDS or the MS JDBC driver, you can use the same liquibase.database.core.MSSQLDatase class.  The easiest way to get an instance is with:

DatabaseConnection connection = DatabaseTestContext.getInstance().getConnection(url);
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(connection);

The MSSQLDatabase class should understand jtds urls.

Nathan

Could anyone post here some example code that I could use with actual version. Lets say that I have following method:

public void updateDb(String url, String login, String password, String diffFilePath, String driverClassName) throws Exception{
//code
}

And the proper driver is in classpath.

Thank you in advance

With 2.0, it is something like this:

    public void updateDb(String url, String login, String password, String diffFilePath, String driverClassName) throws Exception{
            Connection c = //create connection from url/login/password/driverClassName;
            Liquibase liquibase = null;
            try {
                liquibase = createLiquibase©;
                liquibase.update(null);
            } catch (SQLException e) {
                throw new DatabaseException(e);
            } finally {
                if (liquibase != null) {
                    liquibase.forceReleaseLocks();
                }
                if (c != null) {
                    try {
                        c.rollback();
                        c.close();
                    } catch (SQLException e) {
                        //nothing to do
                    }
                }
            }
    }

Nathan

I use Groovy to script my installation. The scripts use the Groovy way to connect to a database and use Groovy SQL (http://groovy.codehaus.org/api/groovy/sql/Sql.html)

I created the minimal script to invoke Liquibase from Groovy:

---------------------
import groovy.sql.Sql
import liquibase.Liquibase
import liquibase.resource.FileSystemResourceAccessor
import liquibase.database.jvm.JdbcConnection
import liquibase.database.Database
import liquibase.database.DatabaseFactory
db = Sql.newInstance( ‘jdbc:oracle:thin:@//localhost:1521/xe
                    , ‘groovy’
                    , ‘secret’
                    , ‘oracle.jdbc.driver.OracleDriver’)
def changeLogFile = "update.xml"
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(db.getConnection()))
def liquibase = new Liquibase( changeLogFile
                             , new FileSystemResourceAccessor()
                                                         , database
                                                         )
liquibase.update(null)
---------------------

Nathan, this would be more elegant if the Liquibase class had a constructor that would take a Connection and set its own FileSystemResourceAccessor. It would then be:

---------------------
import groovy.sql.Sql
import liquibase.Liquibase
db = Sql.newInstance( ‘jdbc:oracle:thin:@//localhost:1521/xe
                    , ‘groovy’
                    , ‘secret’
                    , ‘oracle.jdbc.driver.OracleDriver’)
def changeLogFile = "update.xml"
def liquibase = new Liquibase( changeLogFile
                                                         , db.getConnection()
                                                         )
liquibase.update(null)
---------------------

What do you think?

I explicitly require the ResourceAccessor to be passed because I don’t think we should assume any given resource accessor, including FileSystemResorceAccessor. If we had to pick one, I think ClassLoaderResourceAccessor is the more standard one, but there are a lot of use cases that do not use it. 


Therefore, I think it’s best to make choosing it a conscious choice of anyone using the liquibase API.


Nathan