2013-12-03 42 views
18

我正在使用JNDI创建tomcat连接池。它在Web应用程序中很有用。我相信InitialContext是由tomcat服务器提供的。独立Java程序中的Initialcontext

Context initContext = new InitialContext(); 
Context envContext = (Context)initContext.lookup("java:/comp/env"); 
dataSource = (DataSource)envContext.lookup("jdbc/testdb"); 

但是,当我尝试从独立的Java程序调用相同的实用程序时,initContext对象为空。我如何显式提供Context对象所需的所有必要属性。

错误:javax.naming.NoInitialContextException:需要环境或系统属性指定类 名,或者作为一个小程序参数,或 应用程序中的资源文件:java.naming.factory.initial的

回答

5

您也可以创建自己的自定义上下文。

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

查看Running Beans Locally that use Application Server Data Sources了解更多详情。


newUPDATE

你可以使用Spring的类org.springframework.mock.jndi.SimpleNamingContextBuilder。例如:

  • 设置:

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

    DataSource ds = InitialContext.doLookup("jdbc/Oracle"); 
    
+0

请注意,当你链接的文章最后评论指出,该解决方案是马车:如果名称为空或没有找到, – Lonzak

+0

嘿,@Lonzak我加了一个StackOverflowException为查找过程中抛出更新。 –

0

Tomcat提供上下文&与InitialContext类一起使用的DataSource实现。在运行Tomcat时,Context.INITIAL_CONTEXT_FACTORY属性被设置为指向Tomcat的实现。当不运行Tomcat时,您不具备这种能力......您需要使用第三方库(如c3p0)进行连接池。

1

没有办法直接使用Tomcat上下文工厂,请参阅here了解更多有关替代方法的文档。不过我建议你尝试运行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); 

你可以改变Tomcat中的代码也使用这个外部RegistryContext,然后都设置(S)将使用相同的JNDI提供商。这个question看起来非常相似。

17

这是改编自接受的答案,但行内尽一切努力避免的例子创建额外的类。

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(); 
    } 
} 
+3

恭喜!最佳解决方案,干净简单! –

+2

一个伟大的内联解决方案upvote :-) – janhink

+2

这节省了我通过Java的神秘API冲刷几个小时。谢谢! –