Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
独立Java程序中的Initialcontext_Java_Jndi - Fatal编程技术网

独立Java程序中的Initialcontext

独立Java程序中的Initialcontext,java,jndi,Java,Jndi,我正在使用JNDI创建连接池。它在web应用程序中非常有效。我相信InitialContext是由tomcat服务器提供的 Context initContext = new InitialContext(); Context envContext = (Context)initContext.lookup("java:/comp/env"); dataSource = (DataSource)envContext.lookup("jdbc/testdb&quo

我正在使用JNDI创建连接池。它在web应用程序中非常有效。我相信InitialContext是由tomcat服务器提供的

Context initContext  = new InitialContext();
Context envContext  = (Context)initContext.lookup("java:/comp/env");
dataSource = (DataSource)envContext.lookup("jdbc/testdb");
但是当我试图从独立Java程序调用同一个实用程序时,initContext对象为null。如何显式地提供上下文对象所期望的所有必要属性

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


Tomcat提供了使用InitialContext类的上下文和数据源实现。运行Tomcat时,Context.INITIAL\u Context\u工厂属性设置为指向Tomcat的实现。不运行Tomcat时,您没有此能力。。。您需要使用像c3p0这样的第三方库来进行连接池。

没有直接使用Tomcat上下文工厂的方法,请参阅更多关于替代方法的文档。但我建议您尝试在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,然后两个集合将使用相同的JNDI提供程序。这似乎非常相似。

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

LocalContext ctx = LocalContextFactory.createLocalContext();
ctx.addDataSource("jdbc/testdb", driverName, url, usr, pwd);
有关更多详细信息,请参阅


更新

您可以使用Spring类。e、 g:

  • 设置:

  • 使用:


下面是一个根据公认答案改编的示例,但所有操作都是内联的,以避免创建额外的类

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();
    }
}
publicstaticvoidmain(字符串[]args){
setupInitialContext();
//执行查找数据源的操作
}
私有静态void setupInitialContext(){
试一试{
NamingManager.setInitialContextFactoryBuilder(新的InitialContextFactoryBuilder(){
@凌驾
公共InitialContextFactory createInitialContextFactory(哈希表环境)引发NamingException{
返回新的InitialContextFactory(){
@凌驾
公共上下文getInitialContext(哈希表环境)引发NamingException{
返回新的InitialContext(){
私有哈希表数据源=新哈希表();
@凌驾
公共对象查找(字符串名称)引发NamingException{
if(dataSources.isEmpty()){//init dataSources
MysqlConnectionPoolDataSource ds=新的MysqlConnectionPoolDataSource();
ds.setURL(“jdbc:mysql://localhost:3306/mydb");
ds.setUser(“mydbuser”);
设置密码(“mydbpass”);
dataSources.put(“jdbc/mydbname”,ds);
//根据需要向列表中添加更多数据源
}
if(dataSources.containsKey(名称)){
返回dataSources.get(name);
}
抛出新的NamingException(“找不到数据源:“+name”);
}
};
}
};
}
});
}
捕获(纳明异常){
ne.printStackTrace();
}
}

您可以使用blow代码创建初始上下文

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

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

您可以通过对
javax.naming.InitialContext
进行子分类并只实现一小部分方法(通常是
bind
lookup
方法)来创建自己的
上下文

然后,您可以创建数据源,并将其绑定到特定键的初始上下文。在此之后,您就可以在独立Java程序中的任何地方查询JNDI上下文了

以下代码可用于创建自己的上下文:

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);
在代码的其他地方,您可以通过从JNDI上下文检索现有数据源来使用它:

InitialContext ic2 = new InitialContext();
DataSource ds = (DataSource) ic2.lookup(jndiPath);
assertNotNull(ds);
Connection conn = ds.getConnection();
assertNotNull(conn);
conn.close();

祝贺最佳解决方案,简洁明了!这为我节省了数小时的时间,使我得以浏览Java的神秘API。非常感谢。这并不是在避免创建额外的类。这将创建几个匿名类。祝您在测试中好运。请注意,您链接的文章的最后一条评论指出解决方案存在缺陷:如果名称为null或未找到,则在查找过程中抛出StackOverflowException…非常好。设置“保存我的测试”。我操纵接口实现中使用的上下文,我没有使用spring或任何JavaEE技术。我仍然希望在服务器启动时使用本地上下文。
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);
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);
InitialContext ic2 = new InitialContext();
DataSource ds = (DataSource) ic2.lookup(jndiPath);
assertNotNull(ds);
Connection conn = ds.getConnection();
assertNotNull(conn);
conn.close();