Search code examples
javahibernatedatasourcejndidao

Registering MySQL DataSource with JNDI for Hibernate


I have hibernate which connect to database via JNDI datasource.

My purpose: registry DataSource with JNDI to test DAO layer.

Example

Hibernate config

<hibernate-configuration>
    <session-factory name="MySessionFactory">
        <property name="hibernate.connection.datasource">java:jdbc/MysqlMyDS</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- mappings .... ->
</hibernate-configuration>

Get SessionFactory in test class :

Configuration cgf = new Configuration().configure("/META-INF/hibernate.cfg.xml");
SessionFactory iceleadsSessionFactory = cgf.buildSessionFactory();

As the result:

16:04:37,753 ERROR DatasourceConnectionProvider:78 - Could not find datasource: java:jdbc/MysqlIceleadsDS
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

To register JNOI I use example (http://www.roseindia.net/tutorial/java/jdbc/registeringthedatasourcewithjndi.html)

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.ConnectionPoolDataSource;

import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

public class RegisteringJNDIWithDataSource {
        private static void startRegistry() throws RemoteException {
                System.out.println(LocateRegistry.getRegistry());
                LocateRegistry.createRegistry(1059);
                System.out.println("RMI registry Stared.");
        }

        private static InitialContext createInitialContextContext()
                        throws NamingException {
                Properties properties = new Properties();
                properties.put(Context.INITIAL_CONTEXT_FACTORY,
                                "com.sun.jndi.rmi.registry.RegistryContextFactory");
                properties.put(Context.PROVIDER_URL, "rmi://localhost:1059");
                InitialContext initialContextcontext = new InitialContext(properties);
                return initialContextcontext;
        }

        public static void main(String args[]) {
                try {
                        startRegistry();
                        ConnectionPoolDataSource dataSource = new MysqlConnectionPoolDataSource();
                        ((MysqlDataSource) dataSource).setUser("root");
                        ((MysqlDataSource) dataSource).setPassword("root");
                        ((MysqlDataSource) dataSource).setServerName("192.168.10.13");
                        ((MysqlDataSource) dataSource).setPort(3306);
                        ((MysqlDataSource) dataSource).setDatabaseName("student");

                        InitialContext context = createInitialContextContext();
                        context.rebind("Source", dataSource);

                } catch (Exception e) {
                        System.out.println(e.getMessage());
                }
        }
}

Please suggest solution. Thanks!


Solution

  • Your code will work, if you correctly set jndi.properties. This file should be in classpath.

    here is working example:

    Server:

        public static void main(String[] args) throws Exception{
            LocateRegistry.createRegistry(1099);
            ConnectionPoolDataSource dataSource = createDataSource("root", "");
    
            InitialContext context = createContext();
            context.bind("MysqlMyDS", dataSource);
            System.out.println("context created!");
    
        }
    
        private static InitialContext createContext() throws NamingException {
            Properties env = new Properties();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
            env.put(Context.PROVIDER_URL, "rmi://localhost:1099");
            InitialContext context = new InitialContext(env);
            return context;
        }
    
        private static ConnectionPoolDataSource createDataSource(String username, String password) {
            MysqlConnectionPoolDataSource dataSource = new MysqlConnectionPoolDataSource();
            dataSource.setUser(username);
            dataSource.setPassword(password);
            dataSource.setServerName("localhost");
            dataSource.setPort(3306);
            dataSource.setDatabaseName("test");
            return dataSource;
        }
    

    client:

    hibernate.cfg.xml Note: datasource jndi name should be exactly as you set it by context.bind()

    <?xml version='1.0' encoding='utf-8'?>
            <!DOCTYPE hibernate-configuration PUBLIC
                    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.datasource">MysqlMyDS</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    </session-factory>
    </hibernate-configuration>
    

    jndi.properties (if you want, you can set it in code or with -D option)

    java.naming.factory.initial=com.sun.jndi.rmi.registry.RegistryContextFactory
    java.naming.provider.url=rmi://localhost:1099
    

    unit test

    public class TestClient {
        @Test
        public void testCfg() throws Exception {
            Configuration cgf = new Configuration().configure("/hibernate.cfg.xml");
            cgf.buildSessionFactory();
        }
    }