I am making my first steps with Grails and try to create a hello world application with an Oracle Database 12c.
Unfortunately the tutorial documentation on the database specific part at www.grails.org seems not that comprehensive (in contrast for example to that of Ruby on Rails, which I used now several years) - especially when it comes to non-H2 databases.
Is there some recent tutorial on how to get a Grails 3.0.2 app up and running with an Oracle Database 12c?
Mainly I am interested on a) where to put the corresponding JDBC driver and b) how the database configuration should look like.
For a)
grails.org talks about a "lib" directory but does not explain, where it exists or should be created. Other sources say, that the "lib" directory is outdated since several Grails versions and that JDBC drivers should be loaded via dependencies from some repositories - which is obviously not possible with the closed-source Oracle JDBC driver.
For b)
Currently, I have created basic database configuration at <my-app>/grails-app/conf/DataSource.groovy for Oracle 12c:
dataSource {
url = "jdbc:oracle:thin:#my-server:my-port:my-sid"
driverClassName = "oracle.jdbc.OracleDriver"
dialect = "Oracle10gDialect"
username = "my-user"
password = "my-pass"
}
Should that be enough for a simple hello world app?
Everything I have found so far at the web is outdated either on the Grails side (covering versions 2.x oder 1.x) and/or the Oracle side (covering versions 10* oder 11*).
Thanks for any hints!
Update (just for the record and to bring together the comments below):
1)
Edit <myapp>/grails-app/conf/application.yml.
hibernate:
jdbc:
use_get_generated_keys: true
(...)
dataSource:
pooled: true
jmxExport: true
driverClassName: oracle.jdbc.OracleDriver
username: <myuser>
password: <mypassword>
(...)
environments:
development:
dataSource:
dbCreate: create
url: jdbc:oracle:thin:#<myserver>:<myport>:<mysid>
(...)
2)
Get the corresponding Oracle JDBC driver that fits your JDK and Oracle DB release. In my case (openJDK 7 + Oracle 12c) this was ojdbc7.jar release 12.1.0.2.0 from the Oracle Website: http://www.oracle.com/technetwork/database/features/jdbc/index.html
3)
Place this JDBC driver in <myapp>/lib (create this directory, if it does not yet exists).
4)
Add details of this JDBC driver to the dependencies section of <myapp>/build.gradle (modify if necessary to fit your environment/releases):
(...)
dependencies {
(...)
runtime "com.oracle.ojdbc7:12.1.0.2.0"
(...)
}
(...)
5)
Create a Maven artifact (modify if necessary to fit your environment/releases):
mvn install:install-file -Dfile=lib/ojdbc7.jar -DgroupId=com.oracle -DartifactId=ojdbc7 -Dversion=12.1.0.2.0 -Dpackaging=jar -DgeneratePom=true
6)
Add the path to the JDBC driver to your CLASSPATH: export CLASSPATH=/<somewhere>/<myapp>/lib/ojdbc7.jar
7)
Enjoy ...
yes this will be OK for meanwhile. But there are details missing.
I'll post detailed instructions as soon as i get to the office.
Actually there is a sample for mySql somewhere on the grails site, and from it it's pretty clear how to make same for an oracle DB.
I just have created a new app and compared it with myne for oracle 11g.
Here it is:
./build.gradle, add following line to "dependencies" section:
runtime "com.oracle:ojdbc14:10.2.0.3.0"
./grails-app/conf/application.yml, add following to "hibernate" section:
jdbc:
use_get_generated_keys: true
./grails-app/conf/application.yml, dataSource: section should be like:
dataSource:
pooled: true
jmxExport: true
driverClassName: oracle.jdbc.OracleDriver
username: YOURUSERNAME
password: yoursecret
./grails-app/conf/application.yml, environments: configuration, all three environments should be like:
environments:
development:
dataSource:
dbCreate: create
url: jdbc:oracle:thin:#somehost.net:1521:YOURORAINSTANCE
test:
dataSource:
dbCreate: update
url: jdbc:oracle:thin:#somehost.net:1521:YOURORAINSTANCE
production:
dataSource:
dbCreate: update
url: jdbc:oracle:thin:#somehost.net:1521:YOURORAINSTANCE
And the Hibernate dialect for Oracle you have is pretty old one, I think you'd better remove it, without specifying it explicitly all works fine.
You can get the JDBC driver through this maven command.
mvn install:install-file \
-Dfile=/lib/ojdbc7.jar \
-DgroupId=com.oracle \
-DartifactId=ojdbc7 \
-Dversion=12.1.0.1 \
-Dpackaging=jar \
-DgeneratePom=true
download ojdbc7.jar from http://www.oracle.com/technetwork/database/features/jdbc/jdbc-drivers-12c-download-1958347.html
create a <myapp>/lib folder in the main folder of your application (lib folder was removed from Grails 3)
copy ojdbc7.jar to lib folder
add this line to the <myapp>/build.gradle file
dependencies{
(...)
runtime fileTree(dir: 'lib', include: '*.jar')
(...)
}
create lines in the <myapp>/grails-app/conf/application.yml
hibernate:
(...)
jdbc:
use_get_generated_keys: true
dataSource:
pooled: true
jmxExport: true
driverClassName: oracle.jdbc.OracleDriver
username: DBUSERNAME
password: dbpassword
environments:
development:
dataSource:
dbCreate: create
url: jdbc:oracle:thin:#localhost.net:1521:dbname
test:
dataSource:
dbCreate: update
url: jdbc:oracle:thin:#localhost.net:1521:dbname
production:
dataSource:
dbCreate: update
url: jdbc:oracle:thin:#locaLhost.net:1521:dbname
Hibernate as of 2.0.1 (Grails 2.0.1) supported a property "dialect". As shown below. Presume there's a similar property still for newer versions of Hibernate.
File .../grails-app/conf/DataSource.groovy
// Global data source settings
// Note that these global properties values are composited with
// the environment-specific properties under "environments"
dataSource {
pooled = true
driverClassName = "oracle.jdbc.OracleDriver"
...
// Required for function with Oracle 12c and above.
// Not required for Oracle 11.2 and below. For the present works with both.
// Specifying Oracle 10 dialect is sufficient.
// Oracle 12c specific dialect support is not available for Hibernate 2.0.1.
// Works with either ojdbc7 or ojdbc8 jars.
dialect = org.hibernate.dialect.Oracle10gDialect
}
Applying the "dialect" property was sufficient to run older code against both Oracle 11g, 12c. It bought time for code migration to newer versions and dependencies.
Related
I was following some tutorials and docs on how to connect Spring Boot apps with MySQL database but it gives me a start up error all the time even tho I have the url specified in the app.properties file.
spring.datasource.url=jdbc:mysql://localhost:3306/cryptodb01
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jackson.serialization.indent-output=true
I am getting this error everytime I try to run the app:
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
My dependencies are these
according to https://www.testcontainers.org/modules/databases/jdbc/#database-containers-launched-via-jdbc-url-scheme , i'm trying to create an Oracle Container with Quarkus using jdbc url scheme.
After provided a valid docker image ("store/oracle/database-instantclient:12.2.0.1") and set this properties:
"%test":
quarkus:
datasource:
jdbc:
driver: org.testcontainers.jdbc.ContainerDatabaseDriver
url: jdbc:tc:oracle:///databasename
db-kind: other
i get this error:
Container is started (JDBC URL: jdbc:oracle:thin:system/oracle#localhost:32827:xe)
2020-11-09 17:33:06,719 INFO [🐳 .2.0.1]] (Agroal_13889837441) Container store/oracle/database-instantclient:12.2.0.1 started in PT4M7.8483772S
2020-11-09 17:33:06,738 WARN [io.agr.pool] (Agroal_13889837441) Datasource '<default>': Could not create new connection
2020-11-09 17:33:06,805 ERROR [io.qua.application] (main) Failed to start application (with profile test): org.flywaydb.core.internal.exception.FlywaySqlException:
Unable to obtain connection from database: Could not create new connection
--------------------------------------------------------------------------
SQL State : null
Error Code : 0
Message : Could not create new connection
at org.flywaydb.core.internal.jdbc.JdbcUtils.openConnection(JdbcUtils.java:65)
at org.flywaydb.core.internal.jdbc.JdbcConnectionFactory.<init>(JdbcConnectionFactory.java:80)
at org.flywaydb.core.Flyway.execute(Flyway.java:453)
at org.flywaydb.core.Flyway.migrate(Flyway.java:158)
Can someone help me?
If I remember correctly, Flyway community editions (that ships with Quarkus) does not have support for Oracle. You need to use the Enterprise edition.
You need to replace the Quarkus Flyway dependency. Just exclude the one included and add the enterprise one (either in Maven or Gradle).
I have h2 and flyway enabled in my Spring Boot 2 project.
I have properties as follows:
spring.datasource.url: jdbc:h2:mem:mydatabasename
spring.datasource.driverClassName: org.h2.Driver
spring.datasource.username: sa
spring.datasource.password:
spring.jpa.database-platform: org.hibernate.dialect.H2Dialect
spring.h2.console.enabled: true
spring.h2.console.path: /h2
spring.flyway.url: ${spring.datasource.url}
spring.flyway.schemas : mydatabasename
spring.flyway.user: ${spring.datasource.username}
spring.flyway.password : ${spring.datasource.password}
db.migration file is usual (resources/db/migration/V1__Initial_version.sql)
CREATE TABLE PRODUCT
(
ID VARCHAR(200) PRIMARY KEY,
PRODUCTID VARCHAR(30)
);
and it works:
o.f.c.internal.license.VersionPrinter : Flyway Community Edition 5.2.4 by Boxfuse
o.f.c.internal.database.DatabaseFactory : Database: jdbc:h2:mem:mydatabasename (H2 1.4)
o.f.c.internal.database.base.Database : Flyway upgrade recommended: H2 1.4.199 is newer than this version of Flyway and support has not been tested.
o.f.core.internal.command.DbSchemas : Creating schema "mydatabasename" ...
o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table: "mydatabasename"."flyway_schema_history"
o.f.core.internal.command.DbMigrate : Current version of schema "mydatabasename": null
o.f.core.internal.command.DbMigrate : Migrating schema "mydatabasename" to version 1 - Initial version
o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema "mydatabasename" (execution time 00:00.021s)
However when I log in to the H2 console (I use exactly the same url,jdbc:h2:mem:mydatabasename) I do log in, but I do not see anything, only INFORMATION_SCHEMA. Additionally, 'show schemas' show INFORMATION_SCHEMA and
PUBLIC, and PUBLIC not present in the left-hand column also.
I found the fix myself:
making this instruction
spring.datasource.url: "jdbc:h2:mem:mydatabasename;DB_CLOSE_DELAY=-1;"
made the newly created schema and table to appear.
Additionally, if I remove
spring.flyway.schemas : mydatabasename // remove
then the tables created at "root" level when viewing from the console.
Groovy 2.4.12
Oracle Express 11.2.0.2
ojdbc6.jar
I've just installed Oracle Express created a new user with all privileges. I can connect to my xe instance from SQL Developer, so I know its running.
Groovy console, I've added ojdbc6.jar to the classpath and now trying this...
import groovy.sql.Sql;
def cl = Class.forName('oracle.jdbc.OracleDriver')
println cl // outputs 'class oracle.jdbc.OracleDriver'
def db = [
url: 'jdbc:oracle:thin:#localhost:1521:xe',
user: 'me',
password: 'me',
driver: 'oracle.jdbc.OracleDriver']
def sql = Sql.newInstance(db.url, db.user, db.password, db.driver)
I get the SQLException "No suitable driver found for jdbc:oracle:thin:#//localhost:1521/xe".
For the connect string I've also tried jdbc:oracle:thin:#localhost:1521:xe and I've also tried oracle.jdbc.driver.OracleDriver for both loading and the driver parameter.
Is this combo not possible or have I missed something obvious?
EDIT:
Correct connect string is the no-slashes format.
Turns out #tim_yates was almost there.
Needed this...
def f = new File('c:\\oraclexe\\app\\oracle\\product\\11.2.0\\server\\jdbc\\lib\\ojdbc6.jar')
this.getClass().classLoader.rootLoader.addURL(f.toURL())
No idea why MySQL worked without this!
I was using a previous version grails-database-migration plugin for a while and never had any big issues with it. However, lately I upgraded the whole project to grails 3.0.9 and did some additional development, the behavior as follows:
Imported the current prod DB structure into local machine (that DB copy is without the latest changes and new entities)
Execute: grails -Dgrails.env=staging dbm-gorm-diff changlog.xml
What I expected at this point is new changlog.xml file with all changes of existing entities and new ones.
What I get:
Newly defined entities automatically got added into the DB.
The changes in changlog.xml only included the changes of already existing tables, such as:
also, If I try running grails -Dgrails.env=staging run-app
ERROR grails.boot.GrailsApp - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springLiquibase_dataSource': Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: liquibase.integration.spring.SpringLiquibase.createDatabase(Ljava/sql/Connection;Lliquibase/resource/ResourceAccessor;)Lliquibase/database/Database;
FAILURE: Build failed with an exception.
What went wrong: Execution failed for task ':bootRun'.
Process 'command '/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/bin/java''
finished with non-zero exit value 1
...
...
Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. | Error Failed to start server (Use --stacktrace to see the full trace)
Here is the portion of my application.yml
dataSource:
pooled: true
url: jdbc:mysql://127.0.0.1:3306/triz?useUnicode=yes&characterEncoding=UTF-8
driverClassName: "com.mysql.jdbc.Driver"
jmxExport: true
username: root
password: password
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
properties:
jmxEnabled: true
initialSize: 5
maxActive: 50
minIdle: 5
maxIdle: 25
maxWait: 10000
maxAge: 600000
timeBetweenEvictionRunsMillis: 5000
minEvictableIdleTimeMillis: 60000
validationQuery: SELECT 1
validationQueryTimeout: 3
validationInterval: 15000
testOnBorrow: true
testWhileIdle: true
testOnReturn: false
jdbcInterceptors: ConnectionState
defaultTransactionIsolation: 2
environments:
development:
dataSource:
dbCreate: create
# url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
test:
dataSource:
dbCreate: update
url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
staging:
dataSource:
url: jdbc:mysql://127.0.0.1:3306/triz_staging?useUnicode=yes&characterEncoding=UTF-8
and gradle.build
buildscript {
ext {
grailsVersion = project.grailsVersion
}
repositories {
mavenCentral()
mavenLocal()
maven { url "https://repo.grails.org/grails/core" }
}
dependencies {
classpath "org.grails:grails-gradle-plugin:$grailsVersion"
classpath 'com.bertramlabs.plugins:asset-pipeline-gradle:2.5.0'
// classpath 'com.bertramlabs.plugins:less-asset-pipeline:2.6.7'
classpath "org.grails.plugins:hibernate:4.3.10.5"
classpath 'org.grails.plugins:database-migration:2.0.0.RC4'
}
}
...
...
dependencies {
...
compile 'org.liquibase:liquibase-core:3.3.2'
runtime 'org.grails.plugins:database-migration:2.0.0.RC4'
}
UPDATE
I have another way to approach this problem:
My plan was to generate a changelog based on my current prod DB and then generate a diff for the changes I made. Sounds simple and straightforward; however, it didn't work out as expected. Here is what I did:
Dumped prod DB
Removed liquibase tables
Run: grails dbm-generate-changelog changelog-init.xml --add
At this point, I expected changelog-init.xml to contain the current state of DB. But, instead it applied the changes based on my models first, and then tried generating the diff. Eventually, I ended up with a changelog including my entire existing DB with changes applied from gorm.
What am I doing wrong here?
Additional Observations
It looks like, whenever I try to run ANY migration related commands, grails applies all the changes before that, even through my config says:
staging:
dataSource:
dbCreate: ~
url: jdbc:mysql://127.0.0.1:3306/triz_staging?useUnicode=yes&characterEncoding=UTF-8
properties:
jmxEnabled: true
Also tried completely removing dbCreate. Didn't change anything...
I am done, have no idea where to move next!!!
Well, here is a deal...
I am not sure if that was the real reason, but all I did is moved datasource config from application.yml to application.groovy and everything got back to normal.
I would be happy to hear thoughts.
Thanks.