why use JndiObjectFactoryBean to config JNDI datasource did not work?

14,820

Solution 1

The actual lookup in JndiObjectFactoryBean is done in the lifecycle callback method. Either call the method explictly in your @Bean method like this (workaround)

    @Bean
    public DataSource dataSource(){
        JndiObjectFactoryBean jndiObjectFactoryBean =new JndiObjectFactoryBean();
        jndiObjectFactoryBean.setJndiName("jdbc/SpittrDS");
        jndiObjectFactoryBean.setResourceRef(true);
        jndiObjectFactoryBean.setProxyInterface(DataSource.class);
        jndiObjectFactoryBean.afterPropertiesSet();
        return (DataSource) jndiObjectFactoryBean.getObject();  //NULL!!!
    }

Or the better approach. Let your @Bean method return the JndiObjectFactoryBean and manage its lifecyle. Then in your dependent beans that require a DataSource inject the datasource created from the factory

    @Bean
    public JndiObjectFactoryBean dataSource(){
        JndiObjectFactoryBean jndiObjectFactoryBean =new JndiObjectFactoryBean();
        jndiObjectFactoryBean.setJndiName("jdbc/SpittrDS");
        jndiObjectFactoryBean.setResourceRef(true);
        jndiObjectFactoryBean.setProxyInterface(DataSource.class);
        return jndiObjectFactoryBean;
    }

//in your dependnecy

@Bean
public SomeBean someBean(DataSource dataSource){
   //use the injected datasource shich comes from the factory
}

Solution 2

I landed here without realizing this was a problem I had faced in the past - Error Casting Spring's JndiObjectFactoryBean to ConnectionFactory for Solace-MQ JMS

So a workaround (not the preferred way) is to call afterPropertiesSet() on jndiObjectFactoryBean before attempting to getObject()

@Bean
    public DataSource dataSource(){
        JndiObjectFactoryBean jndiObjectFactoryBean =new JndiObjectFactoryBean();
        jndiObjectFactoryBean.setJndiName("jdbc/SpittrDS");
        jndiObjectFactoryBean.setResourceRef(true);
        jndiObjectFactoryBean.setProxyInterface(DataSource.class);
        jndiObjectFactoryBean.afterPropertiesSet();
        return (DataSource) jndiObjectFactoryBean.getObject();  //NOT NULL
    }
Share:
14,820
TIMFUNNY
Author by

TIMFUNNY

who are you

Updated on July 25, 2022

Comments

  • TIMFUNNY
    TIMFUNNY almost 2 years

    when I uss Java-base to config my JNDI. Spring 4.2.5.

    But If I use JndiObjectFactoryBean to config.when I want to get the datasource,the object will be null.

    @Bean
        public DataSource dataSource(){
            JndiObjectFactoryBean jndiObjectFactoryBean =new JndiObjectFactoryBean();
            jndiObjectFactoryBean.setJndiName("jdbc/SpittrDS");
            jndiObjectFactoryBean.setResourceRef(true);
            jndiObjectFactoryBean.setProxyInterface(DataSource.class);
            return (DataSource) jndiObjectFactoryBean.getObject();  //NULL!!!
        }
    

    But if change the method to this,it work well.

    @Bean
        public DataSource dataSource(){
            final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
            dsLookup.setResourceRef(true);
            DataSource dataSource = dsLookup.getDataSource("java:comp/env/jdbc/SpittrDS");
            return dataSource;
        }
    

    I do not know where is the problem.

    Tomcat 9.0 context.xml

    <Context>
    
        <!-- Default set of monitored resources. If one of these changes, the    -->
        <!-- web application will be reloaded.                                   -->
        <WatchedResource>WEB-INF/web.xml</WatchedResource>
        <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
    
        <!-- Uncomment this to disable session persistence across Tomcat restarts -->
        <!--
        <Manager pathname="" />
        -->
    
        <Resource name="jdbc/SpittrDS"
          auth="Container"
          type="javax.sql.DataSource"
          driverClassName="com.mysql.jdbc.Driver"
          url="jdbc:mysql://localhost:3306/spittrds"
          username="root"
          password="1"
          maxActive="100"
          maxIdle="20"
          minIdle="5"
          maxWait="10000"/>
    </Context>
    
  • TIMFUNNY
    TIMFUNNY about 8 years
    I want to know why this method jndiObjectFactoryBean.getObject() return null
  • ekem chitsiga
    ekem chitsiga about 8 years
    As i said the actual lookup is done in the afterPropertiesSet method which Spring calls after the bean has been created. Before that call the object wont have been retrieved from JNDI.
  • Mrinal
    Mrinal about 6 years
    If I have multiple Data sources, then how to select specific one in someBean() ?
  • hello_earth
    hello_earth over 2 years
    check out also here for people struggling with Spring trying to initialize data sources too early, when they cannot yet be looked up via JNDI (it seems) - i couldn't get this to work, but it seems warmer there: stackoverflow.com/questions/32776410/…