How do you configure a JNDI datasource in Grails 3

2019-04-15 03:48发布

问题:

Grails 3 (3.0.9) app is failing to start on a TC server where another 2 Grails 2 apps using each its JNDI datasource are running fine.

It seems that replicating my Grails 2 JNDI settings in Grails 3 is not working (I left everything else default and specified driverClassName, dbCreate and jndiName for my prod datasource settings).

The application has no problem connecting to the MySQL database straight through JDBC. Only JNDI makes it crash with the below exception (fragment)...

ERROR grails.boot.GrailsApp - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.spr
ingframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property
'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Cannot resolve reference to bean 'dat
aSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource': Cannot r
esolve reference to bean 'dataSourceLazy' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with
name 'dataSourceLazy': Cannot resolve reference to bean 'dataSourceUnproxied' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreation
Exception: Error creating bean with name 'dataSourceUnproxied': Invocation of init method failed; nested exception is javax.naming.NoInitialContextException: Need to specify class
name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547) ~[spring-beans-4.1.7.RELEASE.jar:4
.1.7.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476) ~[spring-beans-4.1.7.RELEASE.jar:4.1
.7.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE
]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEASE]
        at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:199) ~[spring-context-4.1.7.RELEA
SE.jar:4.1.7.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:615) ~[spring-context-4.1.7.RELEASE.jar:4.1.7.R
ELEASE]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:465) ~[spring-context-4.1.7.RELEASE.jar:4.1.7.RELEASE]
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686) ~[spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) ~[spring-boot-1.2.5.RELEASE.jar:1.2.5.RELEASE]
        at grails.boot.GrailsApp.run(GrailsApp.groovy:52) [grails-core-3.0.7.jar:3.0.7]
        at grails.boot.GrailsApp.run(GrailsApp.groovy:330) [grails-core-3.0.7.jar:3.0.7]
        at grails.boot.GrailsApp.run(GrailsApp.groovy:319) [grails-core-3.0.7.jar:3.0.7]
        at grails.boot.GrailsApp$run.call(Unknown Source) [grails-core-3.0.7.jar:3.0.7]
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) [groovy-2.4.4.jar:2.4.4]
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) [groovy-2.4.4.jar:2.4.4]
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133) [groovy-2.4.4.jar:2.4.4]
        at miron3.Application.main(Application.groovy:8) [main/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while sett
ing bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Cannot resolve refe
rence to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dat
aSource': Cannot resolve reference to bean 'dataSourceLazy' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error c
reating bean with name 'dataSourceLazy': Cannot resolve reference to bean 'dataSourceUnproxied' while setting constructor argument; nested exception is org.springframework.beans.fa
ctory.BeanCreationException: Error creating bean with name 'dataSourceUnproxied': Invocation of init method failed; nested exception is javax.naming.NoInitialContextException: Need
 to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359) ~[spring-beans-4.1.7.RELEASE.jar:4.1.7.RELEA
SE]
        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) ~[spring-beans-4.1.7.RELEASE.jar:4.1.
7.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1477) ~[spring-beans-4.1.7.RELEA
SE.jar:4.1.7.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1222) ~[spring-beans-4.1.7.RELEASE.jar:

回答1:

your correct above didn't work. I followed below steps, its working now for me.

  1. tomcat context.xml file defined like this:

    Resource name="grailsDB"
    
  2. application.yml added this production datasource.

    production:
        dataSource:
            dbCreate: update
            jndiName: java:comp/env/grailsDB
    
  3. created the grails-app/conf/DataSource.groovy file, based on https://grails.github.io/grails-doc/3.0.x/ref/Plug-ins/dataSource.html document.

    dataSource {
        jndiName = "java:comp/env/grailsDB"
    }
    
  4. created the war file using grails war command.

  5. deployed in tomcat and tested it by adding deleting the sample data.

    Here is software versions I tested with.

APPLICATION STATUS
    Environment: production
    App profile: web
    App version: 0.1
    Grails version: 3.0.3
    Groovy version: 2.4.3
    JVM version: 1.8.0_65

Hope this helps.

thanks -SR



回答2:

In application.yml I replaced url with this value,it work for me. you can try the same.

 production:
        dataSource:
            dbCreate: update            
            jndiName: java:comp/env/jdbc/dbjndiname