java - new InitialContext() 上的无限递归

标签 java jndi

我正在尝试为 Java SE 控制台应用程序设置 JNDI。

我有以下代码:

public class FooMain {

    public static void main (String args[]) throws NamingException {
        Context context = new InitialContext();
        context.bind("foo", "bar");
    }
}

...上下文工厂定义为:

public class MyContextFactory implements InitialContextFactory {

    private static Hashtable store = new Hashtable();

    @Override
    public Context getInitialContext(Hashtable environment) throws NamingException {
        return new InitialContext() {

            @Override
            public void bind(String name, Object obj) {
                store.put(name, obj);
            }

            @Override
            public Object lookup(String name) {
                return store.get(name);
            }    
        };
    }
}

当我使用以下方法调用我的 FooMain 类时:

java -Djava.naming.factory.initial=MyContextFactory -cp ... FooMain

我得到无限递归和最终的 StackOverflow 异常:

Exception in thread "main" java.lang.StackOverflowError
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.naming.internal.VersionHelper12.getContextClassLoader(VersionHelper12.java:185)
at com.sun.naming.internal.ResourceManager.getApplicationResources(ResourceManager.java:549)
at com.sun.naming.internal.ResourceManager.getInitialEnvironment(ResourceManager.java:244)
at javax.naming.InitialContext.init(InitialContext.java:240)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
at MyContextFactory$1.<init>(MyContextFactory.java:20)
at MyContextFactory.getInitialContext(MyContextFactory.java:20)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
at MyContextFactory$1.<init>(MyContextFactory.java:20)
at MyContextFactory.getInitialContext(MyContextFactory.java:20)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
at MyContextFactory$1.<init>(MyContextFactory.java:20)
at MyContextFactory.getInitialContext(MyContextFactory.java:20)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.InitialContext.<init>(InitialContext.java:192)
...

我可以通过创建一个“环境”哈希表,将 MyContextFactory 类的名称放在那里(在“java.naming.factory.initial”键下),然后创建 InitialContext 来使代码正常工作。使用接受 Hashtable 环境的构造函数:

Context context = new InitialContext(environment);

但我的问题是:如何使用无参数构造函数来完成这项工作,并在调用 JVM 时使用“-Djava.naming.factory.initial”提供工厂类的名称?

最佳答案

感谢 Jim Garrison 的建议,答案如下。 问题的关键在于 MyContext 类的构造函数中的 super(true); 调用。

class MyContext extends InitialContext {

    private Hashtable store;

    public MyContext(Hashtable store) throws NamingException {
        super(true);
        this.store = store;
    }

    @Override
    public void bind(String name, Object obj) {
        store.put(name, obj);
    }

    @Override
    public Object lookup(String name) {
        return store.get(name);
    }    

}



public class FooMain {

    private static final int    ANSWER    = 42;
    private static final String JNDI_NAME = "/config/theAnswerToEverything";

    public static void main (String args[]) throws NamingException {
        Context context = new InitialContext();
        putInContext(                    JNDI_NAME, ANSWER);

        int answer = retrieveFromContext(JNDI_NAME);
        Assert.assertEquals(ANSWER, answer);
        System.out.printf("%d\n", answer);
    }


    private static void putInContext(final String key, final Object value) throws NamingException {
        Context context = new InitialContext();
        context.bind(key, value);
    }

    private static int retrieveFromContext(final String key) throws NamingException {
        Context context = new InitialContext();
        return (int) context.lookup(key);
    }
}


public class MyContextFactory implements InitialContextFactory {

    private static Hashtable store = new Hashtable();

    /*
      Do not confuse [store] with [environment]. They serve different
      purposes.
     */

    @Override
    public Context getInitialContext(Hashtable environment) throws NamingException {
        return new MyContext(store);
    }
}

从命令行调用:

$ java -Djava.naming.factory.initial=MyContextFactory -cp [actual classpath] FooMain
42

关于java - new InitialContext() 上的无限递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47699863/

相关文章:

java - 如何将一些自定义Map对象转换为LinkedHashMap?

java - 如何在 Glassfish 服务器上运行的 OSGi 环境中的 Tapestry 应用程序中通过 JNDI 检索 EJB

java - 在 Tomcat 中加载 JNDI 资源时出现 ClassNotFoundException

Java DNSLookup 获取 DNS 属性

java - 无法将类型 [JmsManagedConnectionFactoryImpl] 的值转换为所需类型 [javax.jms.ConnectionFactory]

java - 未显示内部类 Intellij IDEA 错误

java - 在 portlet .jsp 页面中,我连接了一个小程序,之后它抛出异常

java - 如何将属性 ;DB_CLOSE_ON_EXIT=FALSE 设置为 oracle db url?

java - AWS EMR Spark - 获取 CSV 并与 SparkSql api 一起使用

java - 快速排序算法的动画