Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why use JndiObjectFactoryBean to config JNDI datasource did not work?

Tags:

java

spring

jndi

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>
like image 860
TIMFUNNY Avatar asked Apr 12 '16 13:04

TIMFUNNY


People also ask

What is the use of Jndiobjectfactorybean?

The typical usage will be to register this as singleton factory (e.g. for a certain JNDI-bound DataSource) in an application context, and give bean references to application services that need it. The default behavior is to look up the JNDI object on startup and cache it.

Is JNDI used in spring?

We know that DataSource with JNDI is the preferred way to achieve connection pooling and get benefits of container implementations. Today we will look how we can configure a Spring Web Application to use JNDI connections provided by Tomcat.


1 Answers

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
}
like image 51
ekem chitsiga Avatar answered Nov 15 '22 23:11

ekem chitsiga