0
votes

I have two different JNDI datasources in my Grails 3 app. The app starts and runs correctly when not using JNDI (either dev or prod). But when building and running a war in Tomcat with JNDI datasources I get the exception shown below. It seems to originate as a conflict with jmx, but I have tried disabling jmx wherever I see it, in application.yml and in the datasources themselves. Still, the problem persists. Grails 3.2.13, Tomcat 9.

NOTE: Using an Oracle db as the primary database eliminates the problem. It seems to me that the error with Postgres is caused by the default datasource factory in use. That said, I don't know how to correct it; I thought disabling jmx would do it.

application.groovy:

production:
    dataSource:
        jmxEnabled: false
        dbCreate: none
        jndiName: java:comp/env/jdbc/jpmt-prod-db
    dataSources:
        jddt4:
            jmxEnabled: false
            dbCreate: none
            jndiName: java:comp/env/jdbc/jddt4-prod-db

Tomcat xml config:

<Resource   
    name="jdbc/jpmt-prod-db"
    auth="Container"
    type="javax.sql.DataSource"
    url="jdbc:postgresql://<pg_host>:5432/<db>?currentSchema=sch"
    driverClassName="org.postgresql.Driver"
    dialect="org.hibernate.dialect.PostgreSQLDialect"
    username="<user>" 
    password="<pswd>"
    testOnBorrow="true"
    removeAbandonedOnBorrow="true"
    removeAbandonedTimeout="30"
    logAbandoned="true"
    maxActive="20"
    maxIdle="10" 
    minIdle="5"
    minEvictableIdleTimeMillis="1800000"
    timeBetweenEvictionRunsMillis="1800000"
    numTestsPerEvictionRun="3"
    validationQuery="select 1"
    jmxEnabled="false"
    />

<Resource   
    name="jdbc/jddt4-prod-db"
    url="jdbc:oracle:thin:@<host>:<sid>"
    type="oracle.jdbc.pool.OracleDataSource"
    factory="oracle.jdbc.pool.OracleDataSourceFactory"
    driverClassName="oracle.jdbc.OracleDriver"
    dialect="org.hibernate.dialect.Oracle10gDialect"
    user="<user>" 
    password="<pswd>"
    logSql="false"
    removeAbandoned="true"
    removeAbandonedTimeout="30"
    logAbandoned="true"
    maxActive="20"
    maxIdle="10" 
    maxwait="-1"
    minEvictableIdleTimeMillis="1800000"
    timeBetweenEvictionRunsMillis="1800000"
    numTestsPerEvictionRun="3"
    validationQuery="select 1 from dual"
    jmxEnabled="false"
    />

The exception at Grails startup:

2019-02-20 18:24:32,588 ERROR org.springframework.boot.SpringApplication - Application startup failed
org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [org.apache.tomcat.dbcp.dbcp2.BasicDataSource@1485a2ce] with key 'dataSourceUnproxied'; nested exception is javax.management.InstanceAlreadyExistsException: Catalina:type=DataSource,host=localhost,context=/,class=javax.sql.DataSource,name="jdbc/jpmt-prod-db"
    at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:628)
    at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:550)
    at org.springframework.jmx.export.MBeanExporter.afterSingletonsInstantiated(MBeanExporter.java:432)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:781)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:372)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
    at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
    at org.springframework.boot.web.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:151)
    at org.grails.boot.context.web.GrailsAppServletInitializer.createRootApplicationContext(GrailsAppServletInitializer.groovy:57)
    at org.springframework.boot.web.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:86)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:169)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5098)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:743)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:719)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:703)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:630)
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1840)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
    at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:525)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:424)
    at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1585)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:308)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
    at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:424)
    at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:367)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:969)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:839)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1429)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:944)
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:261)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:770)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:682)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492)

Caused by: javax.management.InstanceAlreadyExistsException: Catalina:type=DataSource,host=localhost,context=/,class=javax.sql.DataSource,name="jdbc/jpmt-prod-db" at com.sun.jmx.mbeanserver.Repository.addMBean(Repository.java:437) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerWithRepository(DefaultMBeanServerInterceptor.java:1898) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerDynamicMBean(DefaultMBeanServerInterceptor.java:966) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerObject(DefaultMBeanServerInterceptor.java:900) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:324) at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522) at org.springframework.jmx.support.MBeanRegistrationSupport.doRegister(MBeanRegistrationSupport.java:195) at org.springframework.jmx.export.MBeanExporter.registerBeanInstance(MBeanExporter.java:675) at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:618) ... 54 common frames omitted

1

1 Answers

0
votes

The answer seems to be to set spring's property.

spring.jmx.enabled: false

This link provided the solution: https://github.com/spring-projects/spring-boot/issues/9179