Custom hook before update run

How to to add the custom hook java file should be run before executing the liquibase update .
We need some custom hook to generate the liquibase format file from json format. before running the update statement

We have a relatively new “command pipeline” system which should work, but since it’s new and in beta it’s not well documented yet.

But, there is CommandStep (liquibase 4.7.0 API) (and the AbstractCommandStep convenience class) allows you to plug into the commands you like. They work a lot like a ServletFilter.

You would implement the getOrder method to return when to run. In your case, you’d return ORDER_NOT_APPLICABLE if the command is not “update” and something lower than ORDER_DEFAULT (like ORDER_DEFAULT-10) for “update” so it runs before the normal UpdateCommandStep.

Then you can implement what you want in the run(CommandResultsBuilder) method.

This new “command framework” isn’t fully hooked up in all the integrations yet, however. It is most supported in the CLI and direct java API calls that use it. If you were using something like maven or spring, however, there are hooks outside of liquibase which you can use.

Does that work for you?

Nathan

We are using spring. Can you please explain how we can using hook from outside?

Am new to liquibase so please explain in details so that i can try in project.

If you’re using spring, there is probably an better way yet. By default, spring uses a liquibase.integration.spring.SpringLiquibase which does it’s logic in the afterPropertiesSet() method.

But, you can change the implementation of SpringLiquibase used by spring to be a subclass you create which overrides the afterPropertiesSet() to do whatever logic you need before calling super.afterPropertiesSet().

Something like:

@Configuration
public class SpringLiquibaseConfig {


    private final DataSource dataSource;
    private final Environment environment;

    public SpringLiquibaseConfig(DataSource dataSource, Environment environment) {
        this.dataSource = dataSource;
        this.environment = environment;
    }

    @Bean
    public SpringLiquibase liquibase() {
        MySpringLiquibase liquibase = new MySpringLiquibase();
        liquibase.setDataSource(dataSource);
        liquibase.setChangeLog(environment.getProperty("spring.liquibase.change-log"));
        liquibase.setDefaultSchema(environment.getProperty("spring.liquibase.default-schema"));
        .......
        return liquibase;
    }
}

Nathan

Hi nvoxland,

I actually have the same need as Zabi. I am trying to make it work by defining my own class which implements the AbstractCommandStep class but cannot get it work.

For your info, below is the code of my class:

package liquibase.command;

import liquibase.util.StringUtil;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import java.nio.file.Path;
import java.nio.file.Files;

public class MyHook extends AbstractCommandStep {
    @Override
    public String[][] defineCommandNames() {
        return new String[][]{ new String[] {"update"}};
    }

    @Override
    public int getOrder(CommandDefinition commandDefinition) {
        final String[][] definedCommandNames = defineCommandNames();
        if (definedCommandNames != null) {
            for (String[] thisCommandName : definedCommandNames) {
                if ((thisCommandName != null) && StringUtil.join(Arrays.asList(thisCommandName), " ").equalsIgnoreCase(StringUtil.join(Arrays.asList(commandDefinition.getName()), " "))) {
                    return ORDER_DEFAULT - 10;
                }
            }
        }
        return ORDER_NOT_APPLICABLE;
    }

    @Override
    public void run(CommandResultsBuilder resultsBuilder) {
        System.out.println("MyHook !!!");
        Path file = Paths.get("test.txt");
        DateTime dt = new DateTime();
        DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
        List<String> lines = Arrays.asList(fmt.print(dt));
        Files.write(file, lines, StandardCharsets.UTF_8);
    }
}

Now, the question is, how do I make Liquibase registering this class in the command pipeline? I did create the java file containing this class in the same folder in which I run the liquibase update command but it does not seem to work. Can you help me?

To register the class for discovery, you have to create a META-INF/services/liquibase.command.Command file and put the complete name of your liquibase.command.MyHook class in there

Nathan