Start spring-boot project without datasource configuration on application.properties - spring

I have a spring-boot project where the database configuration should be saved in the first time the user execute the application, after ask for the connection data (server url, username and password). the application.properties file embbed in the WAR file of the application should be something like that:
security.basic.enabled=false
# THYMELEAF (ThymeleafAutoConfiguration)
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false
# Multipart Configuration
spring.servlet.multipart.maxFileSize = 150MB
spring.servlet.multipart.maxRequestSize = 150MB
spring.servlet.multipart.fileSizeThreshold = 5MB
# Setting max size of post requests to 6MB (default: 2MB)
server.tomcat.max-http-post-size=157286400
After the first run, a second application.properties should be created with the database configuration. But right now, when I try run the project with the configuration above, it do not start, showing the following error message:
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
without give the application the change to generate the second configuration file, with the database properties.
How I could force the application to run this first time, even without the database stuff?
update
Ok, then I get rid of this error message by keeping this 2 dependencies on my pom.xml:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.4.1</version>
</dependency>
and now the applications runs without error, and I am able to open the installation page to create the database on the postgresql server and import the initial data (user data included).
But I notice that this initial data is not being stored on the postgresql server (despite the datababse and all the tables are being created normally). I suspect they are being created on the hyperSql database on memory, what do not help me at all.
My guess is that's happen because I autowire some Dao classes for this entities on my InstallService class, and the code only create the data on the postgresql where I directly make the connection with this specific server.
Considering the method responsible by populate de initial data on my database is something like that:
public void criarUsuario(String user, String pass, String nome, String sobrenome, String email) {
Usuario novo = new Usuario();
novo.setUsername(user);
novo.setPassword(pass);
novo.setFirstName(nome);
novo.setLastName(sobrenome);
novo.setEmail(email);
novo.setEnabled(true);
novo.setLocked(false);
novo.setCredenciais(new ArrayList<Credencial>());
novo.getCredenciais().add( credencialDao.findBy("nome", "admin") );
usuarioDao.insert(novo);
...
}
What I could change here to persist this data on the postgresql database, instead of the hyperSql database?
update 2
Now I managed to run the application even with only the postgresql dependency om my pom.xml. I did that by adding a initial configuration on my first application.properties (locatd on /src/main/resources):
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/appdata
spring.datasource.username=...
spring.datasource.password=..
spring.datasource.continue-on-error=true
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=none
spring.jpa.generate-ddl=false
But when I try access the application on the browser, I got an error saying the database not exist (of course not, when I run the application the first time I have a specific flow to create database, tables and populate initial data).
is there any way to supress this "database not exist" error when I run the project?

Related

How does springboot JPA knows which database will be used?

I got to know Java spring JPA a couple days ago and there is one question which really makes me confused.
As I create a repository and use 'save()' method to save some objects into it. How does it know what type of database I am using and which local location to save.
I know I can config database (h2) like:
spring.datasource.url=jdbc:h2:mem/mydb
Then JPA will know: ok you are using h2 database and url is "jdbc:h2:mem/mydb"
However, some people said this config is not mandatory. If without this config, how does JPA knows which database I gonna use?
From the spring-boot documentation:
You should at least specify the URL by setting the spring.datasource.url property. Otherwise, Spring Boot tries to auto-configure an embedded database.
The following class is responsible for providing default settings for embedded DB: org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
public String determineDatabaseName() {
...
if (this.embeddedDatabaseConnection != EmbeddedDatabaseConnection.NONE) {
return "testdb";
}
...
}
This answer can also be helpful: Where does the default datasource url for h2 come from on Spring Boot?

Why I can't find my tables in H2 schema / How can I validate which H2 schema my Spring boot app is working with?

I'm running a spring boot app
didn't have any setting for h2 other than maven
when i'm connecting to the h2 console i can see the tables that were supposed to be created for two entities
i connected with the JDBC URL: jdbc:h2:mem:testdb (which is supposed to be the default)
Is there a way to make sure what schemas is H2 currently running/ or some log file for H2 ?
in my application.properties i have this:
spring.h2.console.enabled=true
spring.h2.console.path=/h2
I read somewhere that H2 initializing itself upon login, but a demo i was watching these were the exact steps taken , so not sure that is the case.
these are the settings in the H# console:
You can explicitly instruct spring boot to create and connect to a particular schema in H2 with config as below.
spring.datasource.url=jdbc:h2:~/test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=sa
This creates a datasource of name test database in h2 in file mode. There would be a file called test.db in your home folder which would be the data file for the database.
DB_CLOSE_ON_EXIT property decides to recreate the database on every restart.
There is an easier way to tell Spring JPA the default schema for your H2 data source by just adding the "SET SCHEMA {default schema}" in the datasource url, e.g.:
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS testdb\\;SET SCHEMA testdb
I actually saw the right schema all along
The reason I thought I wasn't seeing the right schema was - the JPA Entities I expected to see, were not there.
I then found that this was because I didn't name the package for the JPA entities correctly
I named it "domain" (see pic):
I should have named it com.example.domain as can be seen:
This is because Spring Boot looks is doing a #ComponentScan "under" the package with the main class , so I had to prefix the "domains" with the name of the package that the main class resides in, which is com.example.
For me I had to check the log when I run Sprinboot
jdbc:h2:mem:9967b201-6b59-4925-acb3-d2e50dc5d9a5. --> this can be any other auto generated UUD
Adding this to your JDPC URL in the browser will let you see the tables that you created.

Flyway Invocation of init method failed

I'm trying to set up Flyway to work with Spring JPA. I'm stuck at:
Error creating bean with name 'org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration$FlywayConfiguration': Invocation of init method failed; nested exception is java.lang.IllegalArgu: name
Stack trace isn't giving me much more to work with. I have a previous database where many entities have a name column. I'm guessing Flyway is having some trouble extracting the existing database schema? I looked trough Spring, Spring Boot, and Flyway docs, but couldn't find anything for this.
I have a PostgreSQL database. Here are the related dependencies from my pom.xml:
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.2-1002.jdbc4</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>4.0.3</version>
</dependency>
Here is my Flyway configuration in application.properties:
flyway.baseline-version=1
flyway.baseline-on-migrate=true
flyway.check-location=true
flyway.locations=${MIGPATH}
I think locations is correct, because I had a mistake with it earlier and after fixing that, the error message changed. It's a path to a folder with 1 file called V1__f.sql - here are its contents:
ALTER TABLE category ADD hidden boolean NOT NULL;
ALTER TABLE expense ADD details VARCHAR(256);
Since the error was related to name and my migrations don't concern that field, I'm guessing this error is not caused by the contents of the migration file. In any case I believe the contents of the migration file is correct (my previously existing database + those 2 changes should be compatible with the schema implicitly defined by my JPA entity definitions).

Spring Boot. #DataJpaTest H2 embedded database create schema

I have couple of entities in my data layer stored in particular schema. For example:
#Entity
#Table(name = "FOO", schema = "DUMMY")
public class Foo {}
I'm trying to setup H2 embedded database for integration testing of my data layer.
I'm using #DataJpaTest annotation for my tests to get H2 embedded database configured automatically. However, the creation of tables fails because schema DUMMY is not created at DB initialization.
Any ideas on how to create schema before creation of tables in test cases?
I've tried to use #Sql(statements="CREATE SCHEMA IF NOT EXISTS DUMMY") but didn't succeed.
Also, I've tried to set spring.datasource.url = jdbc:h2:mem:test;INIT=CREATE SCHEMA IF NOT EXISTS DUMMY in my test.properties file together with TestPropertySource("classpath:test.properties"), but that didn't work too.
I had the same issue, I managed to resolve by creating schema.sql (in resources folder) with the content
CREATE SCHEMA IF NOT EXISTS <yourschema>
Documentation can be found here but imho the lack of real examples make it very complex.
Warning: this script is also executed within the normal (not test) environment.
Not mandatory, but good practice, add h2 dependency only in test scope
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
I think you are looking for this annotation:
#AutoConfigureTestDatabase(replace=Replace.NONE)
example:
#DataJpaTest
#AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
class UserRepoTest {...}
After couple hours of struggling I've found a workaround.
You can define spring.jpa.properties.hibernate.default_schema = DUMMY in your application.properties.
And then set spring.jpa.properties.hibernate.default_schema = in your test.properties and use together with #TestPropertySource("classpath:test.properties")
So, in this way the schema DUMMY won't be created and the entities will be created in default schema.
In my case schema.sql under test/resources din't worked.
The following configuration in test/resources/application.yml file worked.
spring:
datasource:
username: sa
password: sa
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:usrmgmt;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL;INIT=CREATE SCHEMA IF NOT EXISTS DUMMY;
liquibase:
change-log: classpath:db/changelog/db.changelog-master.xml
In the above configuration, provided the below additional configuration
INIT=CREATE SCHEMA IF NOT EXISTS DUMMY extension to the existing DB url. In the absence of this, faced the exception Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Schema "DUMMY" not found;.
spring.liquibase.change-log property. In the absence of this, faced the exception Caused by: liquibase.exception.ChangeLogParseException: classpath:/db/changelog/db.changelog-master.yaml does not exist.

Spring Boot / Spring Data import.sql doesn't run Spring-Boot-1.0.0.RC1

I've been following the development of Spring Boot, and sometime between the initial version 0.0.5-BUILD-SNAPSHOT and the current version I am using 1.0.0.RC1 I am no longer running my import.sql script.
Here is my configuration for LocalContainerEntityManager and JpaVendorAdapter
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource);
lef.setJpaVendorAdapter(jpaVendorAdapter);
lef.setPackagesToScan("foo.*");
return lef;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(true);
hibernateJpaVendorAdapter.setGenerateDdl(true);
hibernateJpaVendorAdapter.setDatabase(Database.POSTGRESQL);
return hibernateJpaVendorAdapter;
}
Interesting the hibernate.hbm2ddl.auto still seems to run, which I think is part of the definition of my SpringBootServletInitializer
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {
However, I also noticed that the tables generated no longer have underscores and changed their shape when generated?
However, that could be the result of updating my org.postgresql version like so:
Previously:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.2-1004-jdbc41</version>
</dependency>
Now:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.3-1100-jdbc41</version>
</dependency>
I also had to change pggetserialsequence to pg_get_serial_sequence to get the script to run at all from pgadmin?
I guess I'm confusing what's going on, but most importantly I want to get back to having my import.sql run.
I have been following the sample project: https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-data-jpa
And their import.sql isn't running either on 1.0.0-BUILD-SNAPSHOT
The import.sql script is a Hibernate feature I think (not Spring or Spring Boot). It must be running in the sample otherwise the tests would fail, but in any case it only runs if ddl-auto is set to create the tables. With Spring Boot you should ensure that spring.jpa.hibernate.ddl-auto is set to "create" or "create-drop" (the latter is the default in Boot for an embedded database, but not for others, e.g. postgres).
If you want to unconditionally run a SQL script, By default Spring Boot will run one independent of Hibernate settings if you put it in classpath:schema.sql (or classpath:schema-<platform>.sql where <platform> is "postgres" in your case).
I think you can probably delete the JpaVendorAdapter and also the LocalContainerEntityManagerFactoryBean (unless you are using persistence.xml) and let Boot take control. The packages to scan can be set using an #EntityScan annotation (new in Spring Boot).
The default table naming scheme was changed in Boot 1.0.0.RC1 (so nothing to do with your postgres dependency). I'm not sure that will still be the case in RC2, but anyway you can go back to the old Hibernate defaults by setting spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy.
Hey I came across similar issue. My sql script was not getting invoked initially. Then I tried renaming the file from "import.sql" to "schema.sql", it worked. May be give this a shot. My code can be found here - https://github.com/sidnan/spring-batch-example
In addition to what was already said, it's worth noting you can use the data.sql file to import/intialize data into your tables. Just put your data.sql into the root of the classpath (eg: if you're running a Spring Boot app, you put it in the src/main/resources path).
Like was said before, use it together with the property ddl-auto=create-drop, so that it won't crash trying to insert the existing data.
You can also set up which specific file to execute using the spring.datasource.data property. Check out more info here: http://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html
Note: the schema.sql mentioned before would contain the whole DB definition. If you want to use this, ensure that Hibernate doesn't try to construct the DB for you based on the Java Entities from your project. This is what de doc says:
If you want to use the schema.sql initialization in a JPA app (with
Hibernate) then ddl-auto=create-drop will lead to errors if Hibernate
tries to create the same tables. To avoid those errors set ddl-auto
explicitly to "" (preferable) or "none"

Resources