独立Java程序中的Initialcontext

我正在使用JNDI来创建tomcat连接池。 它在Web应用程序中运行良好。 我相信InitialContext是由tomcat服务器提供的。

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

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

错误:javax.naming.NoInitialContextException:需要在环境或系统属性或applet参数或应用程序资源文件中指定类名:java.naming.factory.initial

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

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

有关更多详细信息请参阅使用Application Server数据源的本地运行Bean


新 UPDATE

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

  • 建立:

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

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

这是一个根据已接受的答案改编的示例,但是内联所有内容以避免创建额外的类。

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

没有办法直接使用Tomcat Context Factory,请参阅此处以获取有关替代方案的更多文档。 但我建议你尝试在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,然后两个set都将使用相同的JNDI提供程序。 这个问题似乎很相似。

Tomcat提供了与InitialContext类一起使用的Context和DataSource实现。 运行Tomcat时,Context.INITIAL_CONTEXT_FACTORY属性设置为指向Tomcat的实现。 当没有运行Tomcat时,你没有这种能力……你需要使用像c3p0这样的第三方库来连接池。

您可以使用强制代码创建初始上下文。

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

如果要创建自定义初始上下文,可以扩展javax.naming.InitailContext类