liquibase.integration.jakarta.cdi.CDILiquibase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of liquibase-cdi-jakarta Show documentation
Show all versions of liquibase-cdi-jakarta Show documentation
Configures Liquibase for use in a CDI 3.0+ environment
package liquibase.integration.jakarta.cdi;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import javax.sql.DataSource;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.spi.Extension;
import jakarta.inject.Inject;
import liquibase.Contexts;
import liquibase.LabelExpression;
import liquibase.Liquibase;
import liquibase.Scope;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.DatabaseException;
import liquibase.exception.LiquibaseException;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.integration.commandline.LiquibaseCommandLineConfiguration;
import liquibase.integration.jakarta.cdi.annotations.LiquibaseType;
import liquibase.logging.Logger;
import liquibase.resource.ResourceAccessor;
import liquibase.util.LiquibaseUtil;
import liquibase.util.NetUtil;
/**
* A CDI wrapper for Liquibase.
*
* Example Configuration:
*
* This CDI configuration example will cause liquibase to run
* automatically when the CDI container is initialized. It will load
* db-changelog.xml
from the classpath and apply it against
* myDataSource
.
*
*
* Various producers methods are required to resolve the dependencies, i.e.
*
* {@literal @}Dependent
* public class CDILiquibaseProducer {
*
* {@literal @}Produces {@literal @}LiquibaseType
* public CDILiquibaseConfig createConfig() {
* CDILiquibaseConfig config = new CDILiquibaseConfig();
* config.setChangeLog("liquibase/parser/core/xml/simpleChangeLog.xml");
* return config;
* }
*
* {@literal @}Produces {@literal @}LiquibaseType
* public DataSource createDataSource() throws SQLException {
* jdbcDataSource ds = new jdbcDataSource();
* ds.setDatabase("jdbc:hsqldb:mem:test");
* ds.setUser("sa");
* ds.setPassword("");
* return ds;
* }
*
* {@literal @}Produces {@literal @}LiquibaseType
* public ResourceAccessor createResourceAccessor() {
* return new ClassLoaderResourceAccessor(getClass().getClassLoader());
* }
*
* }
*
*
* @author Aaron Walker (http://github.com/aaronwalker), Jeroen Peschier (https://github.com/xazap)
*/
@ApplicationScoped
public class CDILiquibase implements Extension {
@Inject
@LiquibaseType
ResourceAccessor resourceAccessor;
@Inject
@LiquibaseType
protected CDILiquibaseConfig config;
@Inject
@LiquibaseType
private DataSource dataSource;
private boolean initialized;
private boolean updateSuccessful;
public boolean isInitialized() {
return initialized;
}
public boolean isUpdateSuccessful() {
return updateSuccessful;
}
@PostConstruct
public void onStartup() {
try {
Logger log = Scope.getCurrentScope().getLog(getClass());
log.info("Booting Liquibase " + LiquibaseUtil.getBuildVersionInfo());
String hostName;
try {
hostName = NetUtil.getLocalHostName();
} catch (Exception e) {
log.warning("Cannot find hostname: " + e.getMessage());
log.fine("", e);
return;
}
if (!LiquibaseCommandLineConfiguration.SHOULD_RUN.getCurrentValue()) {
log.info(String.format("Liquibase did not run on %s because %s was set to false.",
hostName,
LiquibaseCommandLineConfiguration.SHOULD_RUN.getKey()
));
return;
}
if (!config.getShouldRun()) {
log.info(String.format("Liquibase did not run on %s because CDILiquibaseConfig.shouldRun was set to false.", hostName));
return;
}
initialized = true;
performUpdate();
} catch (Throwable e) {
Scope.getCurrentScope().getLog(getClass()).severe(e.getMessage(), e);
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new UnexpectedLiquibaseException(e);
}
}
protected void performUpdate() throws LiquibaseException {
Connection c = null;
Liquibase liquibase = null;
try {
c = dataSource.getConnection();
liquibase = createLiquibase(c);
liquibase.update(new Contexts(config.getContexts()), new LabelExpression(config.getLabels()));
updateSuccessful = true;
} catch (SQLException e) {
throw new DatabaseException(e);
} catch (LiquibaseException ex) {
updateSuccessful = false;
throw ex;
} finally {
if ((liquibase != null) && (liquibase.getDatabase() != null)) {
liquibase.getDatabase().close();
} else if (c != null) {
try {
c.rollback();
c.close();
} catch (SQLException e) {
//nothing to do
}
}
}
}
@SuppressWarnings("squid:S2095")
protected Liquibase createLiquibase(Connection c) throws LiquibaseException {
Liquibase liquibase = new Liquibase(config.getChangeLog(), resourceAccessor, createDatabase(c));
if (config.getParameters() != null) {
for (Map.Entry entry : config.getParameters().entrySet()) {
liquibase.setChangeLogParameter(entry.getKey(), entry.getValue());
}
}
if (config.isDropFirst()) {
liquibase.dropAll();
}
return liquibase;
}
/**
* Subclasses may override this method add change some database settings such as
* default schema before returning the database object.
*
* @param c
* @return a Database implementation retrieved from the {@link liquibase.database.DatabaseFactory}.
* @throws DatabaseException
*/
protected Database createDatabase(Connection c) throws DatabaseException {
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(c));
if (config.getDefaultSchema() != null) {
database.setDefaultSchemaName(config.getDefaultSchema());
}
return database;
}
}