Structure test scripts with liquibase to execute in order with normal scripts - spring

we are using liquibase for migrating database in spring boot application. In resources we have main changelog file which includes other changelogs (1 per version).
We usually differentiate environments by liquibase's context attribute but new we need differentiate data which are only for integration tests, and don't want place it next to normal versioned scripts. Is possible place these integration tests scripts in test's scope of project and execute them in order with normal scripts?
For instance:
main changelog:
<include file="version-1.xml"/>
<include file="version-2.xml"/>
and version 1 sample:
<changeSet id="1ver_1" author="xxx">
<!-- creation of table foo_table -->
</changeSet>
<changeSet id="1ver_2" author="xxx">
<!-- adding column to table foo_table -->
</changeSet>
version 2 sample:
<changeSet id="2ver_1" author="xxx">
<!-- renaming table foo_table to bar_table -->
</changeSet>
I need that if scripts for integration tests will written after script 1ver_1 and will contains inserts, it will be ok if next will be executed 1ver_2 and 2ver_1.
So when db for instegration tests started, scripts will be executed in right order:
1ver_1
test_data for 1ver_1
1ver_2
2ver_1
what is best practice to do that?

I think you should change the way you keep your changesets. Have a look at Liquibase Best Practices.
So your master changelog should look like:
<include file="version-1.1.xml"/>
<include file="version-1.2.xml"/>
<include file="version-2.1xml"/>
If you do this, you can have dedicated master changelog file for integration test. Your integration test's changelog-master.xml will look like this:
<include file="version-1.1.xml"/>
<include file="test_data_version-1.1.xml"/>
<include file="version-1.2.xml"/>
<include file="version-2.1xml"/>
After that you just override property in integration tests:
liquibase.change-log=classpath:integration-liquibase-changeLog.xml
Also you should place integration-liquibase-changeLog.xml and all 'test_data_xx.xml' into integration test module resource or test resource (it depends on project structure). The main idea it should not be provided to production artifacts.

Related

Is there a way to store an actual database scheme close to chagelogs?

I have configured the liquibase migration for my Spring Boot application. Now I have a chagelog folder with all changes and I'd like to have a file with current database scheme because it's convenient. Does liquibase have best practices for storing actual db scheme in Spring Boot project?
Your question is confusing. When you say "a file with current database scheme", are you referring to the actual database with data (such as a SQLite file) or a script to create the database initial state?
If what you want is the actual database, this is not a liquibase concern. You could certainly put the database file in the same folder as the scripts, but that would not make a lot of sense to me. The liquibase scripts should be considered part of your source code, the database is execution environment specific and probably belongs elsewhere.
If you want a script for the initial state, that is absolutely something you can do with liquibase. The command you want is generateChangeLog. This will analyse your existing database and generate a changelog to recreate it. You would then refer to it as the first changelog to execute in your scripts.
java -jar liquibase.jar
--classpath=sqlitejdbc-v<version>.jar
--driver=org.sqlite.JDBC
--url="jdbc:sqlite:exampledb.sqlite"
--changeLogFile=db.changelog.initial-state.xml
generateChangeLog
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
<include file="db.changelog.initial-state.xml" />
<changeSet author="captain" id="diff1">
do some stuff
</changeset>
<changeSet author="captain" id="diff2">
do some more stuff
</changeset>
...

Alfresco Custom Content Type not showing

I have been trying to follow this tutorial about Alfresco custom content types
http://ecmarchitect.com/alfresco-developer-series-tutorials/content/tutorial/tutorial.html#localizing-strings-for-custom-content-models.
However, when I get to the 'Test your changes' step and I go to manage rules, I can't manage to get the custom types created (sc_doc and sc_whitepaper) in the dropdown list.
My share-config-custom.xml:
<!-- Share configuration related to this particular Share module extension, such as:
- Doclib action config
- Form config
- Aspect and Type config
Note. Any configuration related to the whole Share.war webapp
(i.e. not specific to this share extension) should be
placed in the environment specific config:
alfresco/tomcat/shared/classes/alfresco/web-extension/share-config-custom.xml file
-->
<alfresco-config>
<!-- Document Library config section -->
<config evaluator="string-compare" condition="DocumentLibrary">
<aspects>
<!-- Aspects that a user can see -->
<visible>
<aspect name="sc:webable" />
<aspect name="sc:productRelated" />
</visible>
<!-- Aspects that a user can add. Same as "visible" if left empty -->
<addable>
</addable>
<!-- Aspects that a user can remove. Same as "visible" if left empty -->
<removeable>
</removeable>
</aspects>
</config>
<config evaluator="node-type" condition="DocumentLibrary">
<types>
<type name="cm:content">
<subtype name="sc:doc" />
<subtype name="sc:whitepaper" />
</type>
<type name="sc:doc">
<subtype name="sc:whitepaper" />
</type>
</types>
</config>
</alfresco-config>
PS: Do I have to re-run 'mvn install' after every change I make in the .xml using Eclipse?
Any help will be much appreciated!
I know i am posting this answer bit late
and my solution is bit poor, But it works for me :)
I hope it will also work for you.
Strange thing is i am following same tutorial and at the time of 'Test your changes' stage not able to see my custom types on the server.
so to make it working in my share project i have changed place of
share-config-custom.xml
from src/main/resources/META-INF to src/main/amp/config/alfresco/web-extension
and restart alfresco and now able to view my custom types in type list on server.
plz post your answer if you have make done this by any other way :)
thank you.
I am not sure which kind of project you have created from maven artifacts.
Repository AMP archetype
All-In-One (AIO) archetype
Share AMP archetype
Here you can see list of all maven commands.
If you are not using local maven repository then you can go for "mvn package" to generate new AMP files and then deploy them manually on alfresco server.

Using values defined in Liquibase property file inside CDATA tag

Unfortunately we don't use Liquibase built-in tags at work and it's already too late to fix the existing changesets. Has anyone tried to pass parameters to queries wrapped in CDATA tag without modifying the Liquibase maven plugin? However, Adding a new maven build plugin is ok.
<changeSet id="XXXXX" author="Mehrad">
<sql>
<![CDATA[
DO SOMETHING USING THE PARAMETER..
]]>
</sql>
<rollback><sql><![CDATA[ do something else ]]></sql></rollback>
</changeSet>
Liquibase support changelog paramters which I think is what you are looking for. You should be able to use then in CDATA blocks, especially with the later (3.2.2+) versions of Liquibase.

How to reuse Spring context when running Ant junit batchtest

I'm in the process of upgrading our application to JUnit4. I've managed to get our test cases up and running using the Spring annotations
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
We then execute all tests with Ant using
<junit ...>
<batchtest fork="yes" todir="tmp">
<fileset dir="${testsrc.dir}">
<include name="**/Test*.java"/>
</fileset>
</batchtest>
However, based on our logfiles it appears that the Spring context is re-created for every single test class. Thus, total execution time is way too high. What is the proper approach to have the Spring context only loaded once?
Thanks
Simon Niederberger
Maybe it's because of the fork parameter? Seems like ant is creating a fork for each single test.
I guess normally springs junit runner tries to reuse the context.

How do I control spring injections that vary between the test environment and the production environment?

I'm setting up a CI situation in which I will deploy my web app to a test environment. In this test environment, I want the business objects used by the app to be mocks of the real ones; the mocks will return static test data. I'm using this to run tests agains my ui. I'm controlling the injections of these business object dependencies with Spring; it's a struts 2 application, for what that's worth.
My question is Maven related, I think. What is the best way to have my Maven build determine whether or not to build the spring configuration out for injecting the mocks or injecting the real thing? Is this a good use for maven profiles? Other alternatives?
Spring itself has support for profiles (if you're using 3.1 or newer), for a web-application you can use context-parameter to set the active profile for different environments in the web.xml:
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>test</param-value>
</context-param>
Edit: For Maven & Jenkins, you should be able to set the parameter for a build job as follows:
First, let Maven filter your xml-resources (in this example, only files ending with xml are filtered, others are included without filtering) by adding the following into your pom.xml inside the <build> </build> -tags:
<resources>
<resource>
<directory>src/main/webapp</directory>
<filtering>true</filtering>
<includes>
<include>**/*xml</include>
</includes>
</resource>
<resource>
<directory>src/main/webapp</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/*xml</exclude>
</excludes>
</resource>
</resources>
Then, parameterize the context-param in your web.xml:
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>${env.SPRINGPROFILE}</param-value>
</context-param>
Then parameterize the build job in Jenkins to set the desired string parameter for SPRINGPROFILE (for example test or prod): https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Build
It's probably a bad idea to do anything with the build of the web app artifact ( Maven best practice for generating artifacts for multiple environments [prod, test, dev] with CI/Hudson support? ). While you could use various mechanisms to produce a WAR file with different configurations of the Spring injections for different contexts, the WAR artifact should be the same every time it's built.
In order to extract the configuration out of the WAR, I have used Spring 3's ability to pull in override values from an external property file. I define default, i.e. produciton, values of my business objects. And I configure spring to check for the existence of a properties file, something I will deploy when the app is in a testing environment and requires mock injections. If that properties file exists, it's values are injected instead. Here's the relevent bit of the spring config file.
<!-- These are the default values -->
<util:properties id="defaultBeanClasses">
<prop key="myManagerA">com.myco.ManagerAImpl</prop>
<prop key="myManagerB">com.myco.ManagerBImpl</prop>
</util:properties>
<!-- Pull in the mock overrides if they exist. -->
<context:property-placeholder
location="file:///my/location/mockBeans.properties"
ignore-resource-not-found="true"
properties-ref="defaultBeanClasses"/>
<!-- The beans themselves. -->
<bean id="managerA" class="${myManagerA}"/>
<bean id="managerB" class="${myManagerB}"/>
And here is the contents of the external "mockBeans.properties" file:
#Define mock implementations for core managers
myManagerA=com.myco.ManagerAMockImpl
myManagerB=com.myco.ManagerBMockImpl
This works nicely. You can even include the mockBeans.properties file in the actual WAR, if you like, but not in the live location. Then the test environment task would be too move it to the location pointed at by the spring config. Alternatively, you could have the mock properties reside in a completely different project.

Resources