Liquibase migration with H2 and Spring boot - spring

I use Spring boot and H2 DB. I want to include Liquibase in my app. I have have multiple modules app. There are entity, dao, service, controller, etc modules. I created Liquibase files in Dao module.
This is application.property:
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=password
spring.liquibase.change-log=classpath:db/migration/master.xml
This is liquibase.property:
classpath=
changeLogFile=db/migration/master.xml
url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
username=sa
password=password
driver=org.h2.Driver
And here is master.xml:
<?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
https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
<include file="v-1-0-0/changelog-project-v-1.0.0-cumulative.xml"/>
<include file="v-1-0-1/changelog-project-v-1.0.1-cumulative.xml"/>
</databaseChangeLog>
And I have an error:
Invocation of init method failed; nested exception is liquibase.exception.ChangeLogParseException: liquibase.exception.SetupException: The file v-1-0-0/changelog-project-v-1.0.0-cumulative.xml was not found in
- Spring resources
But, I think that I don't need to specify files form master.xml in properties.
Please, help.
enter image description here

Looks like the path to the changelog-project-v-1.0.0-cumulative.xml is incorrect. Try using relativeToChangelogFile="true"
In master.xml put the following:
<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
https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
<include file="v-1-0-0/changelog-project-v-1.0.0-cumulative.xml" relativeToChangelogFile="true"/>
<include file="v-1-0-1/changelog-project-v-1.0.1-cumulative.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

Related

apply migration in all schema that i have using liquibase

I developed a website using spring boot in this application I'm using architecture multi tenant to manage my database. I want to use Liquibase as a DB migration tool. The problem is that when i do migration the new modification(modification means by add new columns to different tables and also add new tables) is only apply in schema public and doesn't apply on the others sachems , what i want , when i do migration i want the new modification apply on all sachems
ps : i'm using hibernate to create new sachems
Liquibase allows dynamic substitution of properties in changelog files. We can configure multiple properties inside a file and then use them wherever required. In your case, we can configure properties "schema1", "schema2" with some value and then use it in changelog file using ${schema1} or ${schema2} syntax as per requirement.
In liquibase.properties file, we will configure these properties as follows:
schema1=ABC
schema2=PQR
Liquibase assigns or prioritizes value for configured property in below order:
As an attribute passed to your liquibase runner.
As a JVM sytem property
As an environment variable
As a CLI attribute if you are running liquibase through command line
In liquibase.properties file
In the parameters block (property element of the DATABASECHANGELOG table)
You can do it as below example code snippet:
1. Adding a column to some table in schema ABC:
<?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.8.xsd">
<changeSet author="authorName" id="some-unique-id" dbms="${dbType}" context="some-context">
<sql endDelimiter=";" splitStatements="true" stripComments="true">
**My SQL query/ transactional logic goes here**
ALTER TABLE "${schema1}"."TableName" ADD COLUMN COLUMNNAME DATATYPE;
</sql>
</changeSet>
</databaseChangeLog>
2. Creating a table in PQR schema:
<?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.8.xsd">
<changeSet author="authorName" id="some_unique_id" dbms="${dbType}" context="some_context">
<createTable tableName="TableName" schemaName="${schema2}">
<column name="id" type="VARCHAR(200)" />
<column name="name" type="VARCHAR(255)"/>
</createTable>
</changeSet>
</databaseChangeLog>
Note: above example is using 2 properties (schema1 and schema2). You can use only even more than that.
If you need help with creating "liquibase.properties" file, visit this link
Cheers!

Start Jetty application but "java.lang.IllegalStateException: Duplicate fragment name"

Sorry if duplicated.
I am using gradle to build my .war file and start my application using Jetty. But I see this error message
java.lang.IllegalStateException: Duplicate fragment name: spring_web for jar:file:/private/var/folders/r7/z7yqbhx10wl9kyw738crggdd0zwztx/T/jetty-0.0.0.0-8080-application-1.0.war-_pplication-1.0-any-/webapp/WEB-INF/lib/spring-web-4.1.9.RELEASE.jar!/META-INF/web-fragment.xml and jar:file:/private/var/folders/r7/z7yqbhx10wl9kyw738crggdd0zwztx/T/jetty-0.0.0.0-8080-cpplication-1.0.war-_pplication-1.0-any-/webapp/WEB-INF/lib/spring-web-4.1.9.RELEASE.jar!/META-INF/web-fragment.xml
I already did some research on internet, but all are talking about jetty-maven-plugin and the solution is to add "<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>" to webAppConfig. But in my application I don't have webAppConfig. Is this only for Maven? How to solve this if I am using Gradle?
Thanks!
you can put jetty.xml under WEB-INF
jetty.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC
"-//Mort Bay Consulting//DTD Configure//EN"
"http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="allowDuplicateFragmentNames">true</Set>
</Configure>
In your WEB-INF/web.xml, look for the tag (should be at the top), and modify atributes to match these values:
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/j2ee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
metadata-complete="true"
..
>

No Spring Bean found in EJB with SpringBeanAutowiringInterceptor

I need some help: I have one EAR-File, containing one WAR-File, one EJB-Jar-File and some "shared" libs:
aopalliance-1.0.jar commons-logging-1.1.1.jar log4j-1.2.16.jar spring-aop-4.0.5.RELEASE.jar spring-beans-4.0.5.RELEASE.jar spring-context-4.0.5.RELEASE.jar spring-context-support-4.0.5.RELEASE.jar spring-core-4.0.5.RELEASE.jar spring-expression-4.0.5.RELEASE.jar
The War File has a Context initializer which find the spring config and loads everything well.
I now want to use another Spring Context for the EJB Jar.
My EJB is defined as
#Stateless(mappedName = "ejb/SpringRocks")
#RemoteHome(com.ibm.websphere.ola.ExecuteHome.class)
#Interceptors(SpringBeanAutowiringInterceptor.class)
public class WolaUseCaseOne {
#Autowired
private DummyService dummyService;
/* ...More stuff here */
Inside the EJB-JAR, there is also a beanRefContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myEjb" name="myEjb" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg value="classpath*:META-INF/spring/simpleEjb.xml" />
</bean>
</beans>
The simpleEjb.xml is is also inside the EJB-Jar and is defining a very simple Bean:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myDummyService" class="com.provinzial.beispielanwendung.batch.wola.DummyServiceImpl" />
</beans>
As described, the WEB Part works perfect, but when the EJB is called, the SpringBeanAutowiringInterceptor is called, but seems to do nothing. What do I have to do, to get a Spring Context created?! My hope was that it is initialized when the EJB is created. I created a Subclass of SpringBeanAutowiringInterceptor with some loggers, but the class is only created, no method is called !
What else do I have to do? Or does anybody have a valid EAR File example?
I think the Problem is that inside the EJB Module no context is initialized...
Greets
Timo
I was facing similar issue with my EJB (no WAR). This is what fixed mine,
I was missing the spring-aop jar on my classpath. I see you have it so good there.
In my ejb-jar.xml file, I set the meta-data flag to true so I did not get prompted on deployment to complete.
I set to "false" for one deployment to see what IBM generated for me. In the ejb-jar.xml it added the following (my MDB is named TaskMDB),
<assembly-descriptor>
<interceptor-binding>
<ejb-name>TaskMDB</ejb-name>
<interceptor-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
<interceptors>
<interceptor>
<interceptor-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</interceptor-class>
<post-activate>
<lifecycle-callback-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</lifecycle-callback-class>
<lifecycle-callback-method>autowireBean</lifecycle-callback-method>
</post-activate>
<pre-passivate>
<lifecycle-callback-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</lifecycle-callback-class>
<lifecycle-callback-method>releaseBean</lifecycle-callback-method>
</pre-passivate>
<post-construct>
<lifecycle-callback-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</lifecycle-callback-class>
<lifecycle-callback-method>autowireBean</lifecycle-callback-method>
</post-construct>
<pre-destroy>
<lifecycle-callback-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</lifecycle-callback-class>
<lifecycle-callback-method>releaseBean</lifecycle-callback-method>
</pre-destroy>
</interceptor>
</interceptors>
Then I added what IBM generated (the assembly-descriptor and interceptors stanzas) back to my ejb-jar.xml and set the metadata-complete back to true.
Then it worked. Hope this helps.
Here is the full ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd">
<display-name>ares-api-uow-ejb</display-name>
<enterprise-beans>
<message-driven id="TaskMDB">
<ejb-name>TaskMDB</ejb-name>
<ejb-class>something.api.uow.ejb.mdb.TaskMDB</ejb-class>
<messaging-type>javax.jms.MessageListener</messaging-type>
<transaction-type>Bean</transaction-type>
</message-driven>
</enterprise-beans>
</ejb-jar>

Webpshere server is not gettin started after adding MDB configuration to ejb-jar xml

I have added MDB configuration to the ejb-jar.xml and ibm-ejb-jar-bnd.xmi files and then restart fails with throwing the below error,if i revert my changes it started working fine.
Error Message: Caused by: java.lang.IllegalStateException: Parent Translator (EnterpriseBeansTranslator(entity|session|message-driven,841888302)) did not find a Child Translator for "message-driven-destination".
Could you please help me to understand the root cause of the issue. Below is the MDB configuration added.Please help me if the issue is due to xsd??
<ejb-jar id="ejb-jar_1" version="2.1" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">
<enterprise-beans>
<message-driven id="MessageDriven_TestJMSMDBL">
<description>Message Driven Bean for JMS Listener TestJMSMDBL</description>
<ejb-name>TestJMSMDBL</ejb-name>
<ejb-class>com.pega.pegarules.internal.etier.mdb.PRJMSListenerBoot</ejb-class>
<transaction-type>Container</transaction-type>
<message-driven-destination id="MessageDrivenDestination_TestJMSMDBL">
<destination-type>javax.jms.Queue</destination-type>
</message-driven-destination>
<env-entry>
<env-entry-name>PRListener</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>TestJMSMDBL</env-entry-value>
</env-entry>
<env-entry>
<env-entry-name>UseCMT</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>true</env-entry-value>
</env-entry>
<ejb-local-ref id="EJBLocalRef_TestJMSMDBL_EngineBMTLocal">
<description/>
<ejb-ref-name>ejb/EngineBMTLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home>com.pega.pegarules.internal.etier.interfaces.EngineLocalHome</local-home>
<local>com.pega.pegarules.internal.etier.interfaces.EngineLocal</local>
<ejb-link>EngineBMT</ejb-link>
</ejb-local-ref>
<ejb-local-ref id="EJBLocalRef_TestJMSMDBL_EngineCMTLocal">
<description/>
<ejb-ref-name>ejb/EngineCMTLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home>com.pega.pegarules.internal.etier.interfaces.EngineLocalHome</local-home>
<local>com.pega.pegarules.internal.etier.interfaces.EngineLocal</local>
<ejb-link>EngineCMT</ejb-link>
</ejb-local-ref>
</message-driven>
</enterprise-beans>
Your MDB definition is not correct. You should have something like below. It should be <message-destination-type> not <message-driven-destination>.
<message-driven id="MyMDB">
<ejb-name>MyMDB</ejb-name>
<ejb-class>ejbs.MyMDBBean</ejb-class>
<messaging-type>javax.jms.MessageListener</messaging-type>
<transaction-type>Container</transaction-type>
<message-destination-type>javax.jms.Queue</message-destination-type>
</message-driven>
Here is the sample binding file. But you can remove binding for message driven from file and then install it using console. You will be able to define mapping there. Afterwards you can export application from the console and you may then extract correct binding file from there.
<?xml version="1.0" encoding="UTF-8"?>
<ejbbnd:EJBJarBinding xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ejb="ejb.xmi" xmlns:ejbbnd="ejbbnd.xmi" xmi:id="EJBJarBinding_1409479703640">
<ejbJar href="META-INF/ejb-jar.xml#ejb-jar_ID"/>
<ejbBindings xmi:type="ejbbnd:MessageDrivenBeanBinding" xmi:id="MessageDrivenBeanBinding_1409479703640" activationSpecJndiName="myActiveSpec" destinationJndiName="eis/as1">
<enterpriseBean xmi:type="ejb:MessageDriven" href="META-INF/ejb-jar.xml#MyMDB"/>
</ejbBindings>
</ejbbnd:EJBJarBinding>

LIQUIBASE: How to install liquibase. I'm having an error with the batch file I created

here is the error saying liquibase is not recognized as an internal/external
command in cmd
http://animobile.info/upload/1/error.bmp
lb_update.bat code1:
#echo off call Liquibase --changeLogFile=update.xml
update.xml coode:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.Liquibase.org/xml/ns/dbchangelog/1.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.Liquibase.org/xml/ns/dbchangelog/1.9 http://www.Liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">
<include file="v000/master.xml" />
</databaseChangeLog>
master.xml code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.Liquibase.org/xml/ns/dbchangelog/1.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.Liquibase.org/xml/ns/dbchangelog/1.9 http://www.Liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">
<preConditions>
<!-- These changes should only be run against a schema with major version 0 -->
<sqlCheck expectedResult="0">
SELECT NVL(MAX(id),0)
FROM databasechangelog
WHERE author='MajorVersion '
</sqlCheck>
</preConditions >
<include file="v000/2009-10-15-73.xml" />
</databaseChangeLog>
The expected result when the lb_update.bat is executed, a confirmation message will appear saying: Migration successful.
How can i fix this please help! Thank you!
Since you have not mentioned the full path of Liquibase.bat file, it will be searched in the current directory which is D:\Projects\lbdemo\trunk in your case. Looks like Liquibase.bat file doesn't exist at the Location D:\Projects\lbdemo\trunk.

Resources