Grails 3 Oracle AssertionFailure on Save action with getGeneratedKeys support not enabled - oracle

Problem: Error 500: Internal Server Error
URI: /listing/save
Class: org.hibernate.AssertionFailure
Message: getGeneratedKeys() support is not enabled
Configuration
Environment: development
App profile: web
App version: 0.1
Grails version: 3.0.1
Groovy version: 2.4.3
JVM version: 1.8.0_45 (64-bit)
Reloading active: true
Available Controllers:
phonebook.ListingController
Operating System: Windows 7
Database: Oracle 11g R2 Enterprise Edition (11.2.0.4 64-bit)
Debug output contains:
Grails application running at http://localhost:8080
ERROR org.hibernate.AssertionFailure - HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: getGeneratedKeys() support is not enabled
ERROR org.grails.web.errors.GrailsExceptionResolver - AssertionFailure occurred when processing request: [POST] /listing/save - parameters:
name: Scott
phone: 555-1212
create: Create
getGeneratedKeys() support is not enabled. Stacktrace follows:
org.hibernate.AssertionFailure: getGeneratedKeys() support is not enabled
at phonebook.ListingController.$tt__save(ListingController.groovy:38) ~[main/:na]
at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:93) ~[grails-core-3.0.1.jar:3.0.1]
at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:90) ~[grails-core-3.0.1.jar:3.0.1]
at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:93) ~[grails-core-3.0.1.jar:3.0.1]
at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:90) ~[grails-core-3.0.1.jar:3.0.1]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_45]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_45]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45]
File: grails-app\controllers\phonebook\ListingController
Line: 38
Content: listing.save flush:true
Reproducing problem:
C:\Dev> grails create-app phonebook
C:\Dev> cd phonebook
Edit: build.gradle
dependencies {
...
runtime "com.oracle:jdbc-lib-ojdbc6:11.2.0.4"
...
}
Note: Oracle client ojdbc6.jar added to local Maven repository at the coordinates specified above.
Edit: grails-app\conf\application.yml
...
dataSource:
pooled: true
jmxExport: true
driverClassName: oracle.jdbc.OracleDriver
username: scott
password: tiger
environments:
development:
dataSource:
dbCreate: update
url: jdbc:oracle:thin:#localhost:1521/sbx1
...
C:\Dev\phonebook> grails create-domain-class phonebook.listing
Edit:grails-app\domain\phonebook\Listing.groovy
package phonebook
class Listing {
String name
String phone
static constraints = {
name maxSize: 50
phone maxSize: 14
}
}
C:\Dev\phonebook> grails generate-all phonebook.listing
C:\Dev\phonebook> grails run-app
The following confirms that the application connected to the database and created the table successfully:
SQL> describe listing
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER(19)
VERSION NOT NULL NUMBER(19)
NAME NOT NULL VARCHAR2(50 CHAR)
PHONE NOT NULL VARCHAR2(14 CHAR)
There are also two sequences created in the schema:
HIBERNATE_SEQUENCE
LISTING_SEQ
Note: These must have been created as a result at my many attempts to modify mapping attributes in the domain class for ID generation.
Action once embedded Tomcat server is running on http://localhost:8080/
Internet Explorer: http://localhost:8080/
Click on link: Available Controllers > phonebook.ListingController
Click on: New Listing
Complete form and click: Create
Result: Grails exception described above
Research and troubleshooting activities:
Problem not present is only change is Oracle to H2/HSQL file/memory database
Discovered hibernate.jdbc.use_get_generated_keys setting but was unsuccessful in resolving issue by placing setting of true in application.yml configuration file
Found multiple references to settings in grails-app/conf/DataSource.groovy but this is Grails 3 which uses application.yml
Attempted multiple attributes in domain class for mapping ID column using generators
Found little to no information in Grails 3 documentation covering this topic
Hibernate documentation covers configuration settings and ID generators but does not provide Grails / Groovy application of that information
Hibernate documentation states that not explicitly setting hibernate.jdbc.use_get_generated_keys results in it being set automatically by jdbc connection database metadata
I attempted to resolve the problem by the following section in grails-app\conf\application.yml:
hibernate:
jdbc:
use_get_generated_keys: true
cache:
queries: false
...
I suspect that the resolution involves specific settings in grails-app\conf\application.yml but have not discovered the correct combination of configuration settings.

Ok, when looking into where in the application.yml configuration file to place the suggestion from the first answer presented I discovered that the hibernate.jdbc.use_get_generated_keys = true setting that I used was actually under the grails block. While never working with yml files previously I was not aware of the potential importance of how the indention and blocks formed configuration settings. When I first made edits to the file I looked to see if there was already a hibernate section, I place this setting in that block thus resulting in a setting of grails.hibernate.jdbc.use_get_generated_keys. I created the setting under a root (no indention) for hibernate and tested. The result was successful completion of the action.
I hope that this post will assist other new users in working with this configuration file which seems out of place in a framework centered around groovy. I will look to see if there is an option in creating a new grails application to utilize a groovy configuration file instead of the yml file.

You could also try switching from the identity-sequence generator (the default for Oracle dialect, I believe), to the seq-hilo:
In Grails 2.x, you do it via:
grails.gorm.default.mapping = {
id generator: 'seqhilo', params: [max_lo: 1000]
}
I assume it would work similarly in 3.x in the application.yml file. This should prevent hibernate from even needing to use the getGeneratedKeys() method as it will bind the id into the insert from it's own in-memory pool instead of doing a seq.nextval in the insert statement.

Had this problem with Oracle 12, fixed by adding
jdbc:
use_get_generated_keys: true
and upgrading oracle jdbc driver to ojdbc7 12.1.0.2 (12.1.0.1 doesn't work)

For Grails 3, Hibernte 4, Oracle 10c+ the following config works.
Hibernate 4 configured in build.gradle, which is by default as of Grails 3.1.6
In application.yml
hibernate:
jdbc:
use_get_generated_keys: true
id:
new_generator_mappings: true
And then in the domain objects configure the id field to use an Oracle sequence for the key such as the following:
class Person {
String name
static constraints = {
id generator:'sequence-identity', params:[sequence:'person_key_seq']
}
}
Oracle only came out with auto-generated ID fields recently, I think 12. But Hibernate 4 only has org.hibernate.dialect.Oracle10gDialect, so you can't use the new Oracle auto-key feature without Hibernate 5. If you can use Hibernate 5 then the Oracle12cDialect is available, which will allow Hibernate and Oracle to just take care of the key generation for you, both in GORM and in SQL when working on the database directly. However, as of Grails 3.1.6 there are issues getting Hibernate 5 to successfully deploy on some servers, so beware if you attempt to switch.

Related

H2: globally_quoted_identifiers seems not be taken into account

I use spring-boot 2.7.6 and H2 2.1.214.
To fix an issue due to the name of some columns that are also keywords in liquibase files (loaded to initialize the H2 database for tests) and entities, I tried to use the globally_quoted_identifiers property as defined here: https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#_quoting_options
So I did it like this:
spring:
jpa:
properties:
hibernate:
globally_quoted_identifiers: true
But I still have the same errors due to keywords (org.h2.jdbc.JdbcSQLSyntaxErrorException) so I do not know if I use it correctly?
As a workaround I have to use NON_KEYWORDS=VALUE,KEY but I would like to manage all keywords globally.

Spring stateMachine persistance with Jpa

I got a problem with persister configuration. The problem is similar to Spring State machine - Table Scripts , but I dont want to generate tables by myself or with liquibase. So I'd like to use StateMachineJpaRepositoriesAutoConfiguration but I can't find info how I should enable it.
I already tried to use #ImportAutoConfiguration and do some stuff in property file, for example:
spring:
statemachine:
data:
jpa:
repositories:
enabled: true
But, unfortunately It didn't work for me, and I still get the error:
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException:
Schema-validation: missing table [action]
Maybe the way with StateMachineJpaRepositoriesAutoConfiguration is not suitable here, so I'm needed any advice
Tried to use embedded H2 and all the tables was created. So the problem was in my spring.jpa.hibernate settings.
So it should be spring.jpa.generate-ddl=true and spring.jpa.hibernate.ddl-auto=create

How to specify utf8 encoding for db and tables, using embedded database MariaDB in Spring application?

Developing web application I'd like to use an embedded database to store data. However instead of proposed in-memory databases I`d like to prefer to use custom one. My choice is MariaDB. I have been ruled with this article how to get MariaDB as embedded database in my project, everything is fine, database appears, except one thing: I cannot change an encoding for my tables values.
I tried to set additional application properties in my application.yml file, tried to complete connection string with parameters of specifying encoding, but all those stuff didn't work unfortunately :(
May any of you have ever faced with such problem and can help me? Thank you in advance!
My current application.yml is following:
mariaDB4j:
dataDir: ./localMariaDB
port: 3307
databaseName: embeddedDB
spring:
datasource:
url: jdbc:mariaDB://localhost:3307/
username: root
password:
driver-class-name: org.mariadb.jdbc.Driver
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
hibernate:
ddl-auto: create
And finally I get exception bellow:
Caused by: java.sql.SQLException: Incorrect string value: '\xD0\x92 \xD1\x80\xD0...' for column 'current_status' at row 1
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.readErrorPacket(AbstractQueryProtocol.java:1688) ~[mariadb-java-client-2.6.2.jar:na]
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.readPacket(AbstractQueryProtocol.java:1550) ~[mariadb-java-client-2.6.2.jar:na]
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.getResult(AbstractQueryProtocol.java:1513) ~[mariadb-java-client-2.6.2.jar:na]
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.executeQuery(AbstractQueryProtocol.java:318) ~[mariadb-java-client-2.6.2.jar:na]
... 121 common frames omitted
By the way, when I run the application, the connection string which I get looks like jdbc:mysql://localhost:3307/embeddedDB.
I am confused why there is :mysql: instead of :mariadb: as specified in my connection properties. Does it have an influence on my database behavior?
So, I have found the resolution to my issue.
It appeared as usual very simple :)
To change standard character encoding, which MariaDB proposes, I had to specify additional configuration properties before setting up the MariaDB's DataSource.
As this source provides to configure MariaDBSpringService entity to further use in DataSourceconfiguration, it is necessary to extend it (MariaDBSpringService) with some character encoding description utils. So, to specify custom encoding (i.e. to change standard one) I've just added the following lines of code to MariaDBSpringService bean:
service.getConfiguration().addArg("--character-set-server=utf8mb4");
service.getConfiguration().addArg("--collation-server=utf8mb4_general_ci");
In general, the full bean declaration is below:
#Bean
public MariaDB4jSpringService mariaDB4jSpringService(){
MariaDB4jSpringService service = new MariaDB4jSpringService();
service.getConfiguration().addArg("--character-set-server=utf8mb4");
service.getConfiguration().addArg("--collation-server=utf8mb4_general_ci");
return service;
}
Hope, this will help somebody, who further can possibly face with such issue))
Thanks to everybody, who tried to help me!

How to use HSQLDB as a datasource in Websphere Application Server?

I try to set up a local development infrastructure and I want to use HSQLDB as a datasource with my WAS 6.1. I already know that I have to use Apache DBCP to get a connection pooling, but I'm stuck when my application tries to get the first connection.
What I've done
In WAS I created a JDBC provider with the class org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS and removed everything from the classpath input field. Then I put commons-dbcp.jar, commons-pool.jar and hsqldb.jar in MYAPPSERVERDIRECTORY/lib/ext.
Then I created a new datasource with that provider. I added the following custom properties:
driver=org.hsqldb.jdbc.JDBCDriver
url=jdbc:hsqldb:file:///C:/mydatabase.db;shutdown=true
user=SA
password=
My Problem
When I run my application and the first connection to the database is made, I get the following exception:
---- Begin backtrace for Nested Throwables
java.sql.SQLException: No suitable driverDSRA0010E: SQL-Status = 08001, Fehlercode = 0
at java.sql.DriverManager.getConnection(DriverManager.java:592)
at java.sql.DriverManager.getConnection(DriverManager.java:196)
at org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS.getPooledConnection(DriverAdapterCPDS.java:205)
at com.ibm.ws.rsadapter.spi.InternalGenericDataStoreHelper$1.run(InternalGenericDataStoreHelper.java:918)
at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)
at com.ibm.ws.rsadapter.spi.InternalGenericDataStoreHelper.getPooledConnection(InternalGenericDataStoreHelper.java:955)
at com.ibm.ws.rsadapter.spi.WSRdbDataSource.getPooledConnection(WSRdbDataSource.java:1437)
at com.ibm.ws.rsadapter.spi.WSManagedConnectionFactoryImpl.createManagedConnection(WSManagedConnectionFactoryImpl.java:1089)
at com.ibm.ejs.j2c.FreePool.createManagedConnectionWithMCWrapper(FreePool.java:1837)
at com.ibm.ejs.j2c.FreePool.createOrWaitForConnection(FreePool.java:1568)
at com.ibm.ejs.j2c.PoolManager.reserve(PoolManager.java:2338)
at com.ibm.ejs.j2c.ConnectionManager.allocateMCWrapper(ConnectionManager.java:909)
at com.ibm.ejs.j2c.ConnectionManager.allocateConnection(ConnectionManager.java:599)
at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:439)
at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:408)
Any tips on this? I suspect I'm using a wrong class from hsqldb, or maybe my JDBC url is wrong...
In the example given in BDCP docs, the org.hsqldb.jdbcDriver class is used as the driver. The org.hsqldb.jdbc.JDBCDriver is supported only in HSQLDB 2.x, but the other class is supported by all versions of HSQLDB.

Spring Security Core Grails Plugin Issue

I have just read the basic information for the spring security core grails plugin and installed it in my grail project :
grails install-plugin spring-security-core
After that I have used s2-quickstart providing by the plugin :
grails s2-quickstart com.springsecurity SpringUser SpringRole
So basically it has created required Login and Logout controllers, domain controllers and some view/gsp files for me.
Now for testing purpose I need to test one of the controller, so I have created one sample controller which is named as Secure with following code :
package com.springsecurity;
import grails.plugins.springsecurity.Secured;
class SecureController {
#Secured(['ROLE_ADMIN'])
def index = {
render 'Secure access only'
}
}
Now from the documentation I have found one step where it's showing me to create a default user and it's role from Bootstrap.groovy. So I have write the following piece of code in Bootstrap.groovy :
def adminRole = new SpringRole(authority: 'ROLE_ADMIN').save(flush: false)
def userRole = new SpringRole(authority: 'ROLE_USER').save(flush: false)
String password = springSecurityService.encodePassword('password')
def testUser = new SpringUser(username: 'me', enabled: true, password: password)
testUser.save(flush: false)
SpringUserSpringRole.create testUser, adminRole, true
assert SpringUser.count() == 1
assert SpringRole.count() == 2
assert SpringUserSpringRole.count() == 1
One thing I would like to know here is that I have not created any table yet in the backend. So is it required at this step or the above code will store the single user in the session ?
With above piece of code I am getting following exception at the time of running the project :
2010-11-11 11:42:47,932 [main] ERROR context.GrailsContextLoader - Error executing bootstraps: getFlushMode is not valid without active transaction
org.hibernate.HibernateException: getFlushMode is not valid without active transaction
at $Proxy16.getFlushMode(Unknown Source)
at BootStrap$_closure1.doCall(BootStrap.groovy:29)
at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:251)
at grails.util.Environment.executeForEnvironment(Environment.java:244)
at grails.util.Environment.executeForCurrentEnvironment(Environment.java:220)
at org.grails.tomcat.TomcatServer.start(TomcatServer.groovy:164)
at grails.web.container.EmbeddableServer$start.call(Unknown Source)
at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy:158)
at _GrailsRun_groovy$_run_closure5_closure12.doCall(_GrailsRun_groovy)
at _GrailsSettings_groovy$_run_closure10.doCall(_GrailsSettings_groovy:280)
at _GrailsSettings_groovy$_run_closure10.call(_GrailsSettings_groovy)
at _GrailsRun_groovy$_run_closure5.doCall(_GrailsRun_groovy:149)
at _GrailsRun_groovy$_run_closure5.call(_GrailsRun_groovy)
at _GrailsRun_groovy.runInline(_GrailsRun_groovy:116)
at _GrailsRun_groovy.this$4$runInline(_GrailsRun_groovy)
at _GrailsRun_groovy$_run_closure1.doCall(_GrailsRun_groovy:59)
at RunApp$_run_closure1.doCall(RunApp.groovy:33)
at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
at gant.Gant.withBuildListeners(Gant.groovy:427)
at gant.Gant.this$2$withBuildListeners(Gant.groovy)
at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
at gant.Gant.dispatch(Gant.groovy:415)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.executeTargets(Gant.groovy:590)
at gant.Gant.executeTargets(Gant.groovy:589)
Application context shutting down...
Application context shutdown.
After seeing the above error, I am feeling that it's actually trying to store the specified object (in Bootstrap.groovy) to database and there is no table so it's throwing some exception.
Any help would be highly appreciated...
Thanks in advance..
The error message is "getFlushMode is not valid without active transaction" which doesn't have anything to do with whether there are tables or not.
If you're using dbCreate=create-drop or dbCreate=update in DataSource.groovy then all of the tables for your domain classes will be created for you. If you've disabled dbCreate then yes, you'll need to create the associated tables, but this is necessary any time you add one or more domain classes to a Grails app.
Looking at the Grails User mailing list it looks like this is a jar file conflict from something you added to your lib directory or something added by another plugin. One user found that Drools 4.0 was the problem when he saw this error. Do you have plugins that include Hibernate jars, or other libraries that Hibernate depends on, e.g. Antlr?
Got it finally...
Just commented following line in hibernate.cfg.xml
<property name="current_session_context_class">thread</property>
Not sure if you saw this but there is a pretty detailed walkthrough on how to do this here:
http://blog.springsource.com/2010/08/11/simplified-spring-security-with-grails/
Specifically it seems that your hibernate code is not contained within a hibernate session (which your test code probably is not setting up properly) and thus the error message. Typically you want to configure hibernate with hibernate.hbm2ddl.auto to have it auto-create tables and such.
For more information on hibernate.hbm2ddl.auto you can look here:
Hibernate hbm2ddl.auto possible values and what they do?
Grant

Resources