2013-12-03 81 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沖刷幾個小時。謝謝! –