Connecting to HSQL DB from Spring - spring

I start HSQL DB with a Maven plugin (I use the DB in integration tests):
<plugin>
<groupId>com.btmatthews.maven.plugins.inmemdb</groupId>
<artifactId>inmemdb-maven-plugin</artifactId>
<version>1.4.3</version>
<configuration>
<monitorKey>inmemdb</monitorKey>
<monitorPort>11527</monitorPort>
</configuration>
<executions>
<execution>
<id>run</id>
<goals>
<goal>run</goal>
</goals>
<phase>pre-integration-test</phase>
<configuration>
<daemon>true</daemon>
<type>hsqldb</type>
<database>MY_DB</database>
<username>user1</username>
<password>111</password>
</configuration>
</execution>
<execution>
<id>stop</id>
<goals>
<goal>stop</goal>
</goals>
<phase>post-integration-test</phase>
</execution>
</executions>
</plugin>
When the DB is up and running I am able to create a JDBC connection:
Class.forName("org.hsqldb.jdbcDriver");
Connection connection = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost:9001/MY_DB", "sa", "");
System.out.print(connection);
This code prints: org.hsqldb.jdbc.JDBCConnection#2d22efc3.
However, when I try to use the same connection settings to configure a data source in Spring, I get an exception (java.net.ConnectException: Connection refused):
<bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001/MY_DB" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
I also tried username:user1 and password:111, it produces another exception: org.hsqldb.HsqlException: invalid authorization specification - not found: user1.
How can I connect to this DB from Spring?

On the advice of counsel, I am adding as answer that your hsql db was not running when you tried to connect from Spring.

Related

Liquibase on multiple databases

I have already implemented Liquibase with Maven. We are currently using a single database (db2) but now we need to add a new database to the application which will have different objects.
I've seen that i can define a new profile in maven but i couldn't find out how to differentiate which objects is being created on which database.
Is there a solution to this? Can I support 2 different databases with different objects using liquibase?
As you can see in the documentation, you can use two different executions, like this:
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.0.5</version>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<changeLogFile>PATH_TO_CHANGELOG_1</changeLogFile>
... connection properties ...
</configuration>
<goals>
<goal>update</goal>
</goals>
</execution>
<execution>
<phase>process-resources</phase>
<configuration>
<changeLogFile>PATH_TO_CHANGELOG_2</changeLogFile>
... connection properties ...
</configuration>
<goals>
<goal>update</goal>
</goals>
</execution>
</executions>
</plugin>
The only problem with this approach is that you need two different changelog.xml files, one per database.
Also, you can have preconditions in your changelog file to choose between what changeset will be processed by each database.
For example:
<changeSet id="1" author="bob">
<preConditions onFail="MARK_RAN">
<dbms type="oracle" />
</preConditions>
<comment>Comments should go after preCondition. If they are before then liquibase usually gives error.</comment>
<dropTable tableName="oldtable"/>
</changeSet>
The onFail="MARK_RAN" makes Liquibase skip the changeset but marks it as run, so the next time it will not try again. See the customPrecondition tag in the documentation for more complex preconditions.
You may want to have 2 separate changelogs to manage the two databases, even if they are both used by the same application.
As Arturo says you can have 2 or more execution-nodes, but you must give every execution-node a seperate id.
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.0.5</version>
<executions>
<execution>
<id>db1-update</id>
<phase>process-resources</phase>
<configuration>
<changeLogFile>src/main/resources/org/liquibase/db1.xml</changeLogFile>
<driver>org.postgresql.Driver</driver>
<url>jdbc:postgresql://localhost/db1</url>
<username>..</username>
<password>..</password>
</configuration>
<goals>
<goal>update</goal>
</goals>
</execution>
<execution>
<id>db2-update</id>
<phase>process-resources</phase>
<configuration>
<changeLogFile>src/main/resources/org/liquibase/db2.xml</changeLogFile>
<driver>org.postgresql.Driver</driver>
<url>jdbc:postgresql://localhost/db2</url>
<username>...</username>
<password>...</password>
</configuration>
<goals>
<goal>update</goal>
</goals>
</execution>
<execution>
<id>db3-update</id>
<phase>process-resources</phase>
<configuration>
<changeLogFile>src/main/resources/org/liquibase/db3.xml</changeLogFile>
<driver>org.postgresql.Driver</driver>
<url>jdbc:postgresql://localhost/db3</url>
<username>...</username>
<password>...</password>
</configuration>
<goals>
<goal>update</goal>
</goals>
</execution>
</executions>
</plugin>
You can use Preconditions inside changeset or changelog and give conditions according to the database,
<preConditions onFail="WARN">
<dbms type="oracle" />
<runningAs username="SYSTEM"/>
</preConditions>
Like this, you can use precondition tag inside changeset and give conditions according to each database.
Use this link for additions documentation.
Old question but I still answer cause I have the same requirement today, and I am opting for another solution.
I would recommend, if you can, as proposed already in the answers to use seperate changelogs.
But if you want to keep the changelogs unified, as I need for my specific case, I would use labels instead of preconditions to filter changesets to be executed.
<changeSet id="0001:1" author="oz" labels="clickhouse">
<sql>...SOMESQL...</sql>
</changeSet>
<changeSet id="0001:2" author="oz" labels="mongodb">
<ext:createCollection collectionName="myCollection">
...SOMEJSON....
</ext:createCollection>
</changeSet>
This will prevent poluting the databasechangelog of the two databases with the executions of the changesets of the other database.
This will cause problems(for the current release at least 4.6.1) for any liquibase operation using tags, such as rollbackToTag or updateToTag.

batch updating manifest.mf for existing jars using maven

I would like to add a custom key/value pair to the MANIFEST.MF of several existing jar files in my war project (those jars are not the project dependencies).
I already can pack/repack those jars using an ant task.
I read about "manifest" task, how can I apply that task to a fileset (if there is a way)? Thanks in advance.
This is my first answer at StackOverflow. Hope it suits you :)
I've done it like this:
<target name="xxx.modifyManifests">
<echo message="Modifying jar manifests to add trusted-library" />
<apply executable="jar">
<arg value="umf" />
<arg line="${xxx.resources}/manifest/custom_manifest.mf" />
<srcfile />
<fileset dir="${xxx.target}/applets" includes="*.jar" />
</apply>
</target>
The call is a simple one using maven-antrun-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>xxx.modifyManifests</id>
<phase>compile</phase>
<configuration>
<target>
<property environment="windows" />
<property name="xxx.resources"
value="${project.build.directory}/../src/main/resources" />
<property name="xxx.target"
value="${project.build.directory}/${project.artifactId}-${project.version}" />
<ant antfile="${basedir}/build.xml">
<target name="xxx.modifyManifests" />
</ant>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
And my custom_manifest.mf is like this:
Trusted-Only: true
Trusted-Library: true

Integration tests using jetty, hsql, jndi, and spring

I am attempting to create some integration tests for my Spring web app using Jetty accessing a local HSQL database. The goal: run the tests using Selenium (or similar), mock/stub out all external systems, and setup a HSQL database to hit instead of our shared Oracle database. The tests are started during a maven build (the integration-test phase).
The database is initialized by Spring's "jdbc:initialize-database", and is registered as a JNDI datasource in Jetty.
After days of trying different configuration, I have finally gotten to the point where the database is created, initialized, and I think registered as a Jetty resource, but when the test cases run, it just hangs; I think because it is waiting for the database to become available.
Maven configuration
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.3.3</version>
<executions>
<execution>
<id>start</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
<configuration>
<container>
<containerId>jetty7x</containerId>
<dependencies>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
</dependency>
</dependencies>
</container>
<configuration>
<home>${project.build.directory}/cargo/configurations/jetty7x</home>
<properties>
<cargo.jetty.createContextXml>false</cargo.jetty.createContextXml>
<cargo.datasource.datasource>
cargo.datasource.url=jdbc:hsqldb:file:../../../myDB|
cargo.datasource.driver=org.hsqldb.jdbcDriver|
cargo.datasource.username=sa|
cargo.datasource.password=|
cargo.datasource.type=javax.sql.DataSource|
cargo.datasource.jndi=jdbc/myDataSource
</cargo.datasource.datasource>
</properties>
</configuration>
<deployables>
<deployable>
<location>target/myApp</location>
<properties>
<context>myApp</context>
</properties>
</deployable>
</deployables>
</configuration>
</plugin>
Spring configuration
<bean id="localDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="org.hsqldb.jdbcDriver"/>
<property name="jdbcUrl" value="jdbc:hsqldb:file:target/myDB"/>
<property name="user" value="sa"/>
<property name="password" value=""/>
</bean>
<jdbc:initialize-database data-source="mydataSource" ignore-failures="DROPS">
<jdbc:script location="classpath:/sql-scripts/schema/create-schema.sql"/>
<jdbc:script location="classpath:/sql-scripts/schema/create-tables.sql"/>
<jdbc:script location="classpath:/sql-scripts/testdata/data-load.sql"/>
</jdbc:initialize-database>
I am probably missing something, I tried to piece together the configuration through advice from many other posts. Any help would be appreciated.
The recommended method of using HSQLDB for tests, especially complex test setups, is running a Server.
Initially, you start an HSQLDB server using the shell, independently of your test setup. Use the Server property server.silent=false to see immediately the connections and statements on the console.
After some progress has been made, you can customize the server settings. See the Guide:
http://www.hsqldb.org/doc/2.0/guide/listeners-chapt.html
And a summary of different options for testing:
http://www.hsqldb.org/doc/2.0/guide/deployment-chapt.html#dec_app_dev_testing
You may need to use the MVCC transaction model. This reduces the locks and sometimes avoids the connections hanging as a result of on one waiting for the other to commit.

Starting jetty with spring xml as a background process/thread

My goal is to set up a jetty test server and inject a custom servlet to test some REST classes in my project. I was able to launch the server with spring xml and run tests against that server. The issue I'm having is sometimes after the server started, the process stopped at the point before running the tests. It seems jetty didn't go to background. It works every time on my computer. But when I deployed to my CI server, it doesn't work. It also doesn't work when I'm on VPN. (Strange.)
The server should be completed initialized as when the tests stuck, I was able to access the server using a browser.
Here is my spring context xml:
....
<bean id="servletHolder" class="org.eclipse.jetty.servlet.ServletHolder">
<constructor-arg ref="courseApiServlet"/>
</bean>
<bean id="servletHandler" class="org.eclipse.jetty.servlet.ServletContextHandler"/>
<!-- Adding the servlet holders to the handlers -->
<bean id="servletHandlerSetter" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="servletHandler"/>
<property name="targetMethod" value="addServlet"/>
<property name="arguments">
<list>
<ref bean="servletHolder"/>
<value>/*</value>
</list>
</property>
</bean>
<bean id="httpTestServer" class="org.eclipse.jetty.server.Server" init-method="start" destroy-method="stop" depends-on="servletHandlerSetter">
<property name="connectors">
<list>
<bean class="org.eclipse.jetty.server.nio.SelectChannelConnector">
<property name="port" value="#{settings['webservice.server.port']}" />
</bean>
</list>
</property>
<property name="handler">
<ref bean="servletHandler" />
</property>
</bean>
Running latest Jetty 8.1.8 server and Spring 3.1.3. Any idea?
I figured it out. My bad. The IP address for the testing web server (jetty) that my REST client connect to is set to a internal IP address (not localhost) that only available to my local host. So that why the tests couldn't start when I'm on VPN or on CI server.
The xml is actually working and I think it is better than starting jetty in separate ant task. Because spring manage the jetty lifecycle. When the tests finish, spring will shutdown jetty automatically.
If you are using Maven, you can let the jetty-maven-plugin start and stop Jetty as part of your build process. You create your Spring project as usual, add the plugin to your .pom file. mvn jetty:run allows you to run the web app unassembled, and mvn jetty:run-war allows you to run a .war file. I guess that what you really want is to have Jetty started in the pre-integration test phase and stopped in the post integration test phase (ref):
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<stopKey>foo</stopKey>
<stopPort>9999</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>

Maven Exposing properties files appassembler

To load environment specific values, in my src/main/resources folder, I have some properties files in different subfolders i.e.
com/app/ws/webservices-dev.properties
com/app/ws/webservices-test.properties
com/app/jms/jms-dev.properties
com/app/jms/jms-test.properties
I am loading these properties through spring
<bean id="placeholderProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/com/app/jms/jms-${ENVIRONMENT:dev}.properties</value>
<value>classpath:/com/app/ws/webservices-${ENVIRONMENT:dev}.properties</value>
</list>
</property>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="order" value="0" />
</bean>
ENVIRONMENT is environment variable.
I am using appassembler-maven-plugin to generate the executable .sh file.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<binFileExtensions>
<unix>.sh</unix>
</binFileExtensions>
<programs>
<program>
<mainClass>com.app.MainApp</mainClass>
<name>MainApp</name>
</program>
</programs>
</configuration>
</plugin>
As a result of this all my properties files become part of my generated jar file. I want to expose some of the properties to set their values at deployment time. I have tried following configuration
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<configurationSourceDirectory>src/main/resources/com/app/bootstrap</configurationSourceDirectory>
<configurationDirectory>conf</configurationDirectory>
<copyConfigurationDirectory>true</copyConfigurationDirectory>
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
<binFileExtensions>
<unix>.sh</unix>
</binFileExtensions>
<programs>
<program>
<mainClass>com.app.MainApp</mainClass>
<name>MainApp</name>
</program>
</programs>
</configuration>
</plugin>
But Spring does not load the properties; maybe due to the given path in spring config (see above).
What maven configuration should I use to move my properties files in appassembler\conf folder during package time and have spring load them from the classpath. I am after the configuration that works for both development(in eclipse, unit tests as maven builds) and in deployment.

Resources