Liquibase create Schema for postgres - java

I'm using Dropwizard (1.0.0) and Liquibase to create a database if it's not existing.
Problem here is that I'm using a different Postgres schema (not public). It seems like Liquibase is not able to create this schema before is it? I was expecting Liquibase to generate this schema, but it always throws a "Schema with name xx not found" if I try to build the database.

Even though Liquibase does not have CREATE SCHEMA in its bundled changes/refactorings (and therefore doesn't generate one during a dropwizard db dump), you could still include this as a changeset in your migrations changelog using the sql tag, as follows:
<changeSet author="christian" id="1">
<sql dbms="postgresql" endDelimiter=";">
CREATE SCHEMA foo
</sql>
</changeSet>
Note that Liquibase will create it's own tables in the PUBLIC schema, regardless - before applying any changesets:
If you run db migrate --dry-run in dropwizard, you'll see that Liquibase would first execute
CREATE TABLE PUBLIC.DATABASECHANGELOGLOCK ...
CREATE TABLE PUBLIC.DATABASECHANGELOG ...
before running
CREATE SCHEMA foo;

Not directly in answer to the question, but posting it for anyone who ran into the error I did, with creating tables in multiple schemas. I was getting an error executing this from maven with the defaultSchemaName configuration.
[ERROR] Failed to execute goal org.liquibase:liquibase-maven-plugin:3.6.2:update (default-cli) on project demo: Error setting up or running Liquibase: ERROR: relation "databasechangelog" already exists [Failed SQL: CREATE TABLE databasechangelog (ID VARCHAR(255) NOT NULL, AUTHOR VARCHAR(255) NOT NULL, FILENAME VARCHAR(255) NOT NULL, DATEEXECUTED TIMESTAMP WITHOUT TIME ZONE NOT NULL, ORDEREXECUTED INTEGER NOT NULL, EXECTYPE VARCHAR(10) NOT NULL, MD5SUM VARCHAR(35), DESCRIPTION VARCHAR(255), COMMENTS VARCHAR(255), TAG VARCHAR(255), LIQUIBASE VARCHAR(20), CONTEXTS VARCHAR(255), LABELS VARCHAR(255), DEPLOYMENT_ID VARCHAR(10))] -> [Help 1]
I tried to fix it by adding the following configurations to pom.xml, but that was only a partial solution:
<defaultSchemaName>foo</defaultSchemaName>
<changelogSchemaName>foo</changelogSchemaName>
Finally, I got this fixed by adding foo to the end of my connection string also, like this
jdbc:postgresql://localhost:5432/postgres?currentSchema=foo

Liquibase does not have CREATE SCHEMA, you need to manage create schema function by running SQL query.
<changeSet author="liquibase_user" id="1">
<sql>
CREATE SCHEMA IF NOT EXISTS liquibase_demo;
</sql>
</changeSet>

Apart from the fact that you are using Dropwizard then the Spring Boot Pre-Liquibase module does what you are asking.
There's a chicken-and-egg problem with Liquibase in the sense that it cannot be used to configure its own prerequisite, for example a schema. This is the problem which Pre-Liquibase solves. It executes some SQL prior to Liquibase itself.
Sometimes you'll want to host multiple instances of an application on the same database host. Then you'll want to separate them by schema. This is but one possible use-case for Pre-Liquibase.
Pre-Liquibase is meant for Spring so it will not work out-of-the-box for your Dropwizard scenario. But feel free to steal ideas.
(full disclosure: I'm the author of Pre-Libuibase)

Related

Table does not exist - SpringBoot Flyway MySql

I have a springboot application with H2 and have tried out some simple api(s) that does CRUD. Now I am trying to move the db to MySQL running in a docker instance.
I have flyway configured with init script under /resources/db.migration package. I am able to connect to database from my intellij. I am able to build and start the application.
However, upon sending a REST request to save a resource, the app throws an exception. And I see java.sql.SQLSyntaxErrorException: Table 'task-db.customer' doesn't exist in the application log. But after building the project, I could see the customer table created via Flyway. So the table does exist before starting the application.
I tried rebuilding/invalidating cache and restarting intellij but did not help.The only fly configuration I have used is -flyway:locations: classpath:db/migration. Below is the DDL in the flyway init script.
CREATE TABLE IF NOT EXISTS `CUSTOMER` (
`CUSTOMER_ID` int NOT NULL AUTO_INCREMENT,
`FIRST_NAME` varchar(45) DEFAULT NULL,
PRIMARY KEY (`CUSTOMER_ID`)
);`
How can I resolve it? Where should I be looking at? Am I missing something?
Updated the tables to lowercase in the flyway script and entities and that worked.

Envers audit table does not exist when hibernate (via create-drop) tries to delete it

i am using java, spring, hibernate and envers among other things. For testing purposes i use a h2 database and for the test configuration i set spring.jpa.hibernate.ddl-auto=create-drop. Some of my entities are audited (using envers).
Now, when i run my tests i get something like:
2020-04-24 12:05:30.109 DEBUG [org.hibernate.SQL] [Test worker]: alter table nmc.testtable_aud drop constraint FKcmwq41oxs0yus7mgufns1njbd
Hibernate: alter table nmc.testtable_aud drop constraint FKcmwq41oxs0yus7mgufns1njbd
2020-04-24 12:05:30.112 WARN [org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl] [Test worker]: GenerationTarget encountered exception accepting command : Error executing DDL "alter table nmc.testtable_aud drop constraint FKcmwq41oxs0yus7mgufns1njbd" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table nmc.testtable_aud drop constraint FKcmwq41oxs0yus7mgufns1njbd" via JDBC Statement
...
Caused by: org.h2.jdbc.JdbcSQLException: Table "testtable_aud" not found; SQL statement:
When i use spring.jpa.hibernate.ddl-auto=update the described error does not occur, but that causes issues further down the line so it is not an option for me.
While the tests run green on my local developer instance it fails on the central testing machine. Also, this is really annoying since i do not want it to throw an error when there is nothing wrong.
It seems to me that this is a really basic issue. I have searched for some time now and tried different things, but i cannot seems to resolve this conflict. From what i read envers/hibernate integration works well so i cannot believe that this is a common thing which then makes me think that i configured something incorrectly. I just expect that hiberate should only drop tables which already exist or at least produce the appropriate sql.
Any help and/or pointer in the right direction would be greatly appreciated.
Thanks.

Spring Boot -- not running data.sql on Start

I'm trying to run a simple H2 Spring project. I've used starter.spring.io to initialize a project with the web, JDBC, JPA, andH2` dependencies. I'm following along with in28minutes Spring Mastercourse.
All I'm trying to do is initialize one table on startup. I do the following in my data.sql:
CREATE TABLE person
(
id integer not null,
name varchar(255) not null,
location varchar(255),
birth_date timestamp,
primary key(id)
);
My application.properties looks like this:
spring.h2.console.enabled=true
I haven't touched a single other file in the entire project. Just loaded a project, added those lines, and tried running it. For some reason, my table isn't being created. I've gone through the steps in the tutorial probably 15 times by this point and can't find what I'm doing wrong, any help would be greatly appreciated.
Edit: My JDBC URL is correct, as well as my driver class. I've checked those each time I tried re-running the steps
With your exact dependency setup, and with your schema, I can see the data in the web console.
The predefined Generic H2 (embedded) settings should provide the right values, but you should input the following :
Driver Class : org.h2.Driver
JDBC URL : jdbc:h2:mem:testdb
User Name : sa
Password : <empty>
on the web console login page, as those are the defaults for an embedded h2 database.
If you don't see any issue in the startup log, this is most likely it.
Take note that H2 will not error out if you try to connect to a non-existent database.
e.g. : jdbc:h2:mem:db, jdbc:h2:mem:foobar will not produce any errors and connect to empty databases.

Confusing about <security-role> in web.xml

I'm understand that
<security-role><role-name>Admin</role-name></security-role>
is for container map it with tomcat-users.xml (realm)
but I confuse about if I didn't use realm but I use database how container know which field in my database is for role-name or it have naming convention in database field name like "role_name" and container will know it
Thank you for every advices
Just use a database realm and configure the table and column names in a <Realm> element in server configuration file. For Tomcat, this is described in the Realm HOWTO. Here's an extract of relevance, from the JDBCRealm chapter:
Quick Start
To set up Tomcat to use JDBCRealm, you will need to follow these steps:
If you have not yet done so, create tables and columns in your
database that conform to the
requirements described above.
Configure a database username and password for use by Tomcat, that
has at least read only access to the
tables described above. (Tomcat will
never attempt to write to these
tables.)
Place a copy of the JDBC driver you will be using inside the
$CATALINA_HOME/lib directory. Note
that only JAR files are recognized!
Set up a <Realm> element, as described below, in your
$CATALINA_BASE/conf/server.xml file.
Restart Tomcat 6 if it is already running.
Realm Element Attributes
To configure JDBCRealm, you will
create a <Realm> element and nest it
in your $CATALINA_BASE/conf/server.xml
file, as described above. The
attributes for the JDBCRealm are
defined in the Realm configuration
documentation.
Example
An example SQL script to create the
needed tables might look something
like this (adapt the syntax as
required for your particular
database):
create table users (
user_name varchar(15) not null primary key,
user_pass varchar(15) not null
);
create table user_roles (
user_name varchar(15) not null,
role_name varchar(15) not null,
primary key(user_name, role_name)
);
Example Realm elements are included
(commented out) in the default
$CATALINA_BASE/conf/server.xml file.
Here's an example for using a MySQL
database called "authority",
configured with the tables described
above, and accessed with username
"dbuser" and password "dbpass":
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://localhost/authority?user=dbuser&password=dbpass"
userTable="users" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name"/>
Pretty clear, isn't it? If you already have a JDBC datasource configured in Tomcat (for connection pooling and on), then you can also use DataSourceRealm instead.
The tomcat-users.xml which you're talking about is by the way called UserDatabaseRealm.

Autocreate Spring Entity "authorities" during testing

When trying unit tests with Spring Security & Hibernate, none of the security entities "user" or "authorities" are being autocreated. What I have done so far is to write an "user" bo that triggers generation of the appropiate table. However, I am stuck with the authorities:
(as advised by http://java.dzone.com/articles/getting-started-spring for postgresql)
CREATE TABLE authorities
(
username character varying(50) NOT NULL,
authority character varying(50) NOT NULL,
CONSTRAINT fk_authorities_users FOREIGN KEY (username)
REFERENCES users (username) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);
Question: With Hibernate/JPA2, what is the appropiate syntax in order to create a BO representing this query?
Question: Actually, I do not want to create the entry using my own BO. Any better way to make Spring Security or Hibernate create all required tables during test run?
Thanks
Set the hibernate property hibernate.hbm2ddl.auto to update, for example. This should let hibernate automatically create (and update) the tables in needs.
<property name="hibernate.hbm2ddl.auto" value="update" />
Actually, I do not want to create the entry using my own BO. Any better way to make Spring Security or Hibernate create all required tables during test run?
If you don't plan to use Hibernate to interact with these tables, it makes indeed little sense to have Entities for them.
My suggestion would thus be to place the Spring Security tables creation script in an import.sql file and to put this file on the root of the class path and Hibernate will automatically execute it after schema export. See Spring/Hibernate testing: Inserting test data after DDL creation for details (just put your DDL statements on a single line).
Thanks, Pascal, this is just what I have been looking for, however, it does not work. I use maven and put import.sql into the resources dir root (content: CREATE TABLE justatest (aaa character varying(50) NOT NULL );). I also set . Running mvn test copies import.sql to target dir... but nothing happens. logback[debug] does not mention import.sql at all. Any idea where I am going wrong? (Hibernate V 3.5.1-Final)
I'm using this feature with Maven and I cannot reproduce your problem. I have hbm2ddl.auto set to create, my import.sql file is in src/test/resources and it gets executed as expected at the end of the schema export when running tests. Here is the log entry I get (using logback):
20:44:37.949 [main] INFO o.h.tool.hbm2ddl.SchemaExport - Executing import script: /import.sql

Categories