Grails 4.0.3 Multiple Datasources - Second datasource not available in service - grails

I've followed the instructions/example in the Grails Doc (https://docs.grails.org/4.0.3/guide/conf.html#multipleDatasources) and it still uses the default dataSource.
My application.yml contains:
dataSource:
pooled: true
jmxExport: true
dbCreate: validate
url: jdbc:oracle:thin:#XXX.XX.X.XXX:XXXX:TEST
username: username1
password: password1
driverClassName: oracle.jdbc.OracleDriver
dialect: org.hibernate.dialect.Oracle10gDialect
properties:
jmxEnabled: true
initialSize: 5
maxActive: 50
minIdle: 5
maxIdle: 25
maxWait: 10000
maxAge: 600000
timeBetweenEvictionRunsMillis: 5000
minEvictableIdleTimeMillis: 60000
validationQuery: SELECT 1 FROM DUAL
validationQueryTimeout: 3
validationInterval: 15000
testOnBorrow: true
testWhileIdle: true
testOnReturn: false
jdbcInterceptors: ConnectionState
defaultTransactionIsolation: 2 # TRANSACTION_READ_COMMITTED
dataSources:
identityDb:
url: jdbc:oracle:thin:#YYY.YY.YY.YYY:YYYYY:IDENT
username: username2
password: password2
And my service is defined as follows:
class PictureService {
def grailsApplication
def assetResourceLocator
static dataSource = "identityDb"
def getPictures( identifications ) {
// Loop through all ids
for( i in identifications ) {
//try {
Sql sql = Sql.newInstance( dataSource )
...
It throws this stack dump:
ORA-00942: table or view does not exist
. Stacktrace follows:
java.lang.reflect.InvocationTargetException: null
at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:211)
at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.sql.SQLException: ORA-00942: table or view does not exist
When I dump out the connection string information for dataSource, I can see that it's the first datasource listed and not the identityDb datasource. I'm not using domain classes or GORM and am just writing the SQL directly. Any help with this would be appreciated!

Edit / Update
I changed my service to the following and it's working correctly now. I thought I had tried this before but I must not have gotten the correct combination of things in place.
Note that the application.yml did not change.
class PictureService {
def grailsApplication
def assetResourceLocator
def dataSource_identityDb
def getPictures( identifications ) {
// Loop through all ids
for( i in identifications ) {
try {
Sql sql = Sql.newInstance( dataSource_identityDb )
...
Also, this is different that what is listed in the official docs for using a second datasource in Grails 4.0.3.

Related

java.lang.NoClassDefFoundError: com/mysql/jdbc/ParameterBindings

I am seeing this error after the server run for more than one day. There is no error when server starts.
org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method 'onMessage' threw exception; nested exception is java.lang.NoClassDefFoundError: com/mysql/jdbc/ParameterBindings
at grails.plugin.jms.listener.adapter.PersistenceContextAwareListenerAdapter.invokeListenerMethod(PersistenceContextAwareListenerAdapter.groovy:44)
at grails.plugin.jms.listener.adapter.LoggingListenerAdapter.onMessage(LoggingListenerAdapter.groovy:48)
at grails.plugin.jms.listener.adapter.PersistenceContextAwareListenerAdapter.onMessage(PersistenceContextAwareListenerAdapter.groovy:33)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoClassDefFoundError: com/mysql/jdbc/ParameterBindings
at com.mysql.jdbc.ConnectionImpl.clientPrepareStatement(ConnectionImpl.java:1450)
at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4165)
at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4069)
This issue could be due to database inactivity. The following setting might help you to keep the database connectivity active, in case there are none, for a long period of time:
timeBetweenEvictionRunsMillis = 5000
minEvictableIdleTimeMillis = 60000
validationQuery = "SELECT 1"
validationQueryTimeout = 3
validationInterval = 15000
testOnBorrow = true
autoReconnect=true
testWhileIdle = true

grails oracle connection timeout

I have below datasource config in grails.
dataSource_staging_oracle {
dbCreate = "none"
pooled = true
url = "jdbc:oracle:thin:#//my-box-oracle.com:1521/DB1"
driverClassName = "oracle.jdbc.OracleDriver"
username = "USER_1"
password = "encryptedpassword"
passwordEncryptionCodec = PropertiesCodec
}
dataSource_prod_oracle {
dbCreate = "none"
pooled = true
autoReconnect = true
url = "jdbc:oracle:thin:#//my-oracle-prod-box.com:1521/DB2"
driverClassName = "oracle.jdbc.OracleDriver"
username = "user_2"
password = "encrypted_password"
passwordEncryptionCodec = PropertiesCodec
}
Application is able to fetch the DB connection and work fine. However after 1-2 hours of processing, I see connection closed exceptions.
ERROR util.JDBCExceptionReporter - Closed Connection
I believe this has to do with datasource config properties. What grails settings help me in refreshing the connections? I already have set autoReconnect and pooled to true
I use grails 2.3.3
Datasource properties will inform the database what the middleware server will expect from the Database. If your Oracle server does not agree with the settings Grails would like to use, expect sometimes cryptic error messages.
Using pooled connections tells Oracle to hold a number of connections open for the application. If the application is running 1-2 hours and continuously processing, I expect the pool may be running out of valid connections. For some background please view the links included below.
Check out the Grails configuration docs, section 4.4, to see advanced datasource configuration options. Do you have a validation query defined? (eg select 1 from dual;)
Check out this AskTom post for a clear explanation of connection pooling.
Previous StackOverflow question with MySQL but similar error.
Below config helped me fix my problem.
dataSource_staging {
dbCreate = "none"
pooled = true
autoReconnect = true
url = "jdbc:oracle:thin:#//my-box-oracle.com:1521/DB1"
driverClassName = "oracle.jdbc.OracleDriver"
username = "USER_1"
password = "encryptedpassword"
passwordEncryptionCodec = PropertiesCodec
properties {
validationQuery = "SELECT 1 FROM DUAL"
testOnBorrow = true
testWhileIdle = true
testOnReturn = false
timeBetweenEvictionRunsMillis = 5000
minEvictableIdleTimeMillis = 60000
maxAge = 10 * 60000
maxWait = 10000
maxIdle = 25
maxActive = 50
initialSize = 5
}
}

PLS-00201: identifier when running oracle stored procedure through rails

I am running to run an oracle stored procedure in rails, but I am getting the following error:
ActionView::Template::Error (undefined method `parse' for
#<Mysql2::Client:0x00000008ef4310>):
in the following line:
cursor = connection.parse(sql)
This is my database.yml file
development:
adapter: mysql2
database: db1
username: user1
password: *****
host: *****
port: 3306
db1_development:
adapter: mysql2
username: user2
password: ****
database: ****
host: *****
port: 3306
db2_development:
adapter: mysql2
database: user3
username: ******
password: ******
host: *****
port: 3309
db3_development:
adapter: oracle_enhanced
database: user3
username: *****
password: *****
these are my 2 model classes:
module Sts
class StsLtd < Sts::Base
def number
errormsg = nil
errorcode = nil
sperrormsg = nil
vpan = nil
sql =
"BEGIN #{Pkgltd::PKG_LTD}.GET_PAN('
8042049440330819','32', 'TEST', '0',vpan, errormsg, errorcode, sperrormsg);
END;"
connection = self.connection.raw_connection
cursor = connection.parse(sql)
cursor.bind_param(:errormsg, nil, String, 1000)
cursor.bind_param(:errorcode, nil, String, 1000)
cursor.bind_param(:sperrormsg, nil, String, 1000
cursor.bind_param(:vpan, nil, String, 1000)
cursor.exec
vpan, errormsg, errorcode, sperrormsg, vpan = cursor[:vpan], cursor[:errormsg], cursor[:errorcode], cursor[:sperrormsg]
cursor.close
vpan
end
end
end
sts.rb:
module Sts
PKG_LTD ="PKG_LTD"
class Base < ActiveRecord::Base
self.abstract_class = true
establish_connection = "db3_#{Rails.env}"
end
end
I am not sure why it is throwing mysql parse error, when the specific set of code is only trying to connect to the oracle database and running the oracle stored procedure.
EDIT: I was able to fix the parse error by removing the '=' from the following line:
establish_connection = "db3_#{Rails.env}"
However, I am getting the following error:
ActionView::Template::Error (ORA-06550: line 1, column 53: PLS-00201:
identifier 'VAULT' must be declared ORA-06550: line 1, column 7:
PL/SQL: Statement ignored):
My stored procedure works fine if I hardcode "VAULT" as follows:
sql =
"BEGIN #{Pkgltd::PKG_LTD}.GET_PAN('
8042049440330819','32', 'VAULT', '0',vpan, errormsg, errorcode, sperrormsg);
But if I pass it as a function argument and call it, i get the above error:
sql =
"BEGIN #{Pkgltd::PKG_LTD}.GET_PAN('
8042049440330819','32', #{vault_cd}, '0',vpan, errormsg, errorcode, sperrormsg);
OK. So I ran into 3 different errors while running the stored procedure.
The first error was:
ActionView::Template::Error (undefined method `parse' for
#<Mysql2::Client:0x00000008ef4310>):
It was fixed by changing the code from:
establish_connection = "db3_#{Rails.env}"
to
establish_connection "db3_#{Rails.env}"
The second error was:
OCIError: ORA-01036: illegal variable name/number
It was fixed by updating the sql from:
sql =
"BEGIN #{Pkgltd::PKG_LTD}.GET_PAN('
8042049440330819','32', 'VAULT', '0',vpan, errormsg, errorcode, sperrormsg);
to add symbols
sql =
"BEGIN #{Pkgltd::PKG_LTD}.GET_PAN('
8042049440330819','32', 'VAULT', '0',:vpan, :errormsg, :errorcode, sperrormsg);
The final error was:
ActionView::Template::Error (ORA-06550: line 1, column 53: PLS-00201:
identifier 'VAULT' must be declared ORA-06550: line 1, column 7:
PL/SQL: Statement ignored):
For some reason it was not interpreting this as a string.
So I had to add single quotes even for #{vault_cd} to make it work:
sql =
"BEGIN #{Pkgltd::PKG_LTD}.GET_PAN('
8042049440330819','32', '#{vault_cd}', '0',vpan, errormsg, errorcode, sperrormsg);

Grails maxRows/queryTimeout warning

I seem to randomly get the warning below in my Grails 2.2.4 application. It doesn't look like it is causing any issues, but it is still concerning.
I tried to prevent this warning by modifying my datasource properties in my DataSource.groovy file:
dataSource {
pooled = true
properties {
maxWait = 10000 // 10 seconds
minEvictableIdleTimeMillis = 1000 * 60 * 30 // 30 minutes
numTestsPerEvictionRun = 3
testOnBorrow = true
testOnReturn = false
testWhileIdle = false
timeBetweenEvictionRunsMillis = 1000 * 60 * 30 // 30 minutes
validationQuery = "SELECT 1"
}
}
And when that didn't work I tried to set the properties in my BootStrap.groovy file:
def init = { servletContext ->
def ctx = Holders.getApplicationContext()
def dataSource = ctx.dataSourceUnproxied
println "configuring database connection pool"
dataSource.setMinEvictableIdleTimeMillis(1000 * 60 * 30)
dataSource.setTimeBetweenEvictionRunsMillis(1000 * 60 * 30)
dataSource.setNumTestsPerEvictionRun(3)
dataSource.setTestOnBorrow(true)
dataSource.setTestWhileIdle(false)
dataSource.setTestOnReturn(false)
dataSource.setValidationQuery("SELECT 1")
}
Neither attempt prevents the warning. The author of this post said he had success setting the properties directly in the tomcat config, but I need a more generic solution that will work from the command line and in other servers.
2013-09-25 15:07:51,027 [http-bio-8080-exec-9] WARN jdbc.AbstractBatcher - exception clearing maxRows/queryTimeout
java.sql.SQLException: org.apache.commons.dbcp.DelegatingPreparedStatement with address: "com.mysql.jdbc.JDBC4PreparedStatement#13ed0db0: EXCEPTION: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after statement closed." is closed.
at org.apache.commons.dbcp.DelegatingStatement.checkOpen(DelegatingStatement.java:137)
at org.apache.commons.dbcp.DelegatingStatement.getMaxRows(DelegatingStatement.java:237)
at ace_2.DefsUploadController.upload(DefsUploadController.groovy:16)
at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:195)
at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
After connections to my MySQL database timed out I would see that exact exception as well. I updated the DataSource configuration using the suggestion in the Grails docs as a guideline and I have yet to see any exceptions from closed connections.
Here are my current settings:
properties {
initialSize=5
maxActive=50
minIdle=5
maxIdle=25
maxWait = 10000
maxAge = 10 * 60000
timeBetweenEvictionRunsMillis = 5000
minEvictableIdleTimeMillis = 60000
validationQuery = "SELECT 1"
validationQueryTimeout = 3
validationInterval = 15000
testOnBorrow = true
testWhileIdle = true
testOnReturn = false
jdbcInterceptors = "ConnectionState;StatementCache(max=200)"
defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED
}

Doctrine Rollback Issue

I have a weird phenomenom. I added database tables to the schema which are already existing in the database the connect 'virtuemart'. But he can't connect to this tables.
I tried it with
$taxId = Doctrine::getTable('JosVmTaxRate')
->findOneBy('tr.tax_country', 'NZL');
and
$taxId = Doctrine::getTable('JosVmTaxRate')
->findBy('tr.tax_country', 'NZL');
and
$taxId = Doctrine::getTable('JosVmTaxRate')
->findOneBy('tr.tax_country', '"NZL"');
and
$taxId = Doctrine::getTable('JosVmTaxRate')
->createQuery('tr')
->addWhere('tr.tax_country =?', 'NZL')
->execute()
->get(0);
but always the error message
500 | Internal Server Error | Doctrine_Transaction_Exception
Rollback failed. There is no active transaction.
appears.
I checked the schema but I can't find any fault in there:
JosVmTaxRate:
columns:
tax_rate_id: { type: int, notnull: true, unique: true, primary: true, autoincrement: true }
vendor_id { type: int, default: null }
tax_state { type: string(64), default: null }
tax_country { type: string(64), default: null }
mdate { type: int, default: null }
tax_rate { type: decimal(10), scale(4), default: null }
Any idea?
I hope I provided enough information. If not don't hesitate and ask for it.
The code looks alright for me, but the schema not.
What about the colons after vendor_id, tax_state, tax_country, mdate and tax_rate? They are missing.
scale(4) is wrong. scale: 4 is correct.

Resources