Initialcontext in a standalone Java program

前端 未结 6 1431
傲寒
傲寒 2020-12-13 14:38

I\'m using a JNDI for creating tomcat connection pool. It works great in a web application. I believe the InitialContext is provided by the tomcat server.

Co         


        
相关标签:
6条回答
  • 2020-12-13 14:49

    There isn't a way to directly use the Tomcat Context Factory, see here for a little more documentation on the alternatives. But I recommend you try running a registry outside of Tomcat...

    // select the registry context factory for creating a context
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
    
    // specify where that factory is running.
    env.put(Context.PROVIDER_URL, "rmi://server:1099");
    
    // create an initial context that accesses the registry
    Context ctx = new InitialContext(env);
    

    You could change your code in Tomcat to also use this external RegistryContext and then both set(s) would be using the same JNDI provider. This question seems very similar.

    0 讨论(0)
  • 2020-12-13 14:57

    You can create an initial context using blow code.

    InitialContext ic = new InitialContext();
        // Retrieve the Home interface using JNDI lookup
        Object helloObject = ic.lookup("java:comp/env/ejb/HelloBean");
    

    if you want create custom initial context, you can extends javax.naming.InitailContext class

    0 讨论(0)
  • 2020-12-13 14:58

    You can create your own Context by sub-classing javax.naming.InitialContext and implementing only a small subset of methods, typically the bind and the lookup methods.

    Then you can create your data source and bind it to your initial context to a specific key. After this you are ready to go and query from any place your JNDI context in your stand-alone Java programme.

    This is the code you can use to create your own context:

    InitialContext initialContext = new InitialContext() {
    
        private Map<String, Object> table = new HashMap<>();
    
        public void bind(String key, Object value) {
            table.put(key, value);
        }
    
        public Object lookup(String key) throws NamingException {
            return table.get(key);
        }
    };
    
    // Activate the initial context
    NamingManager.setInitialContextFactoryBuilder(environment -> environment1 -> initialContext);
    

    Then you can initialise your data source, whichever you choose:

    InitialContext ic = new InitialContext();
    
    BasicDataSource bds = new BasicDataSource();
    bds.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    bds.setUrl(url);
    bds.setUsername(username);
    bds.setPassword(password);
    
    ic.bind(jndiPath, bds);
    

    And somewhere else in your code, you can use the existing data source by retrieving it from the JNDI context:

    InitialContext ic2 = new InitialContext();
    DataSource ds = (DataSource) ic2.lookup(jndiPath);
    assertNotNull(ds);
    Connection conn = ds.getConnection();
    assertNotNull(conn);
    conn.close();
    
    0 讨论(0)
  • 2020-12-13 15:06

    You could also create your own custom context.

    LocalContext ctx = LocalContextFactory.createLocalContext();
    ctx.addDataSource("jdbc/testdb", driverName, url, usr, pwd);
    

    See Running Beans Locally that use Application Server Data Sources for more details.


    new UPDATE

    You can use the class org.springframework.mock.jndi.SimpleNamingContextBuilder of Spring. e.g.:

    • Setup:

      SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
      builder.bind("jdbc/Oracle", ods);
      builder.activate();
      
    • Use:

      DataSource ds = InitialContext.doLookup("jdbc/Oracle");
      
    0 讨论(0)
  • 2020-12-13 15:06

    Here is an example adapted from the accepted answer but doing everything inline to avoid creating extra classes.

    public static void main(String[] args) {
        setupInitialContext();
        //do something that looks up a datasource
    }
    
    private static void setupInitialContext() {
        try {
            NamingManager.setInitialContextFactoryBuilder(new InitialContextFactoryBuilder() {
    
                @Override
                public InitialContextFactory createInitialContextFactory(Hashtable<?, ?> environment) throws NamingException {
                    return new InitialContextFactory() {
    
                        @Override
                        public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException {
                            return new InitialContext(){
    
                                private Hashtable<String, DataSource> dataSources = new Hashtable<>();
    
                                @Override
                                public Object lookup(String name) throws NamingException {
    
                                    if (dataSources.isEmpty()) { //init datasources
                                        MysqlConnectionPoolDataSource ds = new MysqlConnectionPoolDataSource();
                                        ds.setURL("jdbc:mysql://localhost:3306/mydb");
                                        ds.setUser("mydbuser");
                                        ds.setPassword("mydbpass");
                                        dataSources.put("jdbc/mydbname", ds);
    
                                        //add more datasources to the list as necessary
                                    }
    
                                    if (dataSources.containsKey(name)) {
                                        return dataSources.get(name);
                                    }
    
                                    throw new NamingException("Unable to find datasource: "+name);
                                }
                            };
                        }
    
                    };
                }
    
            });
        }
        catch (NamingException ne) {
            ne.printStackTrace();
        }
    }
    
    0 讨论(0)
  • 2020-12-13 15:06

    Tomcat provides Context & DataSource implementations that work with the InitialContext class. When running Tomcat the Context.INITIAL_CONTEXT_FACTORY property is set to point to Tomcat's implementations. When not running Tomcat, you don't have this ability... you need to use a third-party-library like c3p0 for connection pooling.

    0 讨论(0)
提交回复
热议问题