2017-12-07 1 views
1

Java SE 콘솔 응용 프로그램 용 JNDI를 설정하려고합니다.새로운 InitialContext()에 대한 무한 재귀

나는 다음과 같은 코드가 있습니다

public class FooMain { 

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

중 & hellip을; 상황에 맞는 공장은 다음과 같이 정의된다 :

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) 
... 

내가 수를 내가 사용하여 내 FooMain 클래스를 호출

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

코드는 "environment"Hashtable을 생성하고, MyContextFactory 클래스의 이름을 ("java.naming.factory.initial"키 아래에) 배치 한 다음 InitialContext 해시 테이블 환경 받아들이는 생성자 사용 :

Context context = new InitialContext(environment); 

을하지만 내 질문은 : 나는 "-Djava.naming.factory를 인자없는 생성자를 사용하여 팩토리 클래스의 이름을 공급하는이 일을 할 수있는 방법 .initial "JVM 호출시?

+1

이 흥미로운 질문이다. 'InitialContext'는 실제로 생성자에서 커스텀 팩토리를 찾고 그것을 사용하는 것을 알고있는'Context'를 감싸는 래퍼입니다. JVM을 시작하기 전에 팩토리를 바꾸면 기본 팩토리가 사용되지 않으므로 재귀가 발생합니다. 이 문제를 해결하는 방법을 모르겠지만 InitialContext에 대한 코드를 읽고 기본값이 실행되지 않을 때 일부 동작을 무시하는 것이 좋습니다. –

+1

제안 된 조사 방법 : 익명의 내부 클래스를 사용하지 못할 수도 있습니다. 왜냐하면 당신이'InitialContext'의 초기화 생성자를 사용할 필요가 있다고 생각하기 때문입니다. –

+0

예, 그랬습니다. –

답변

0

짐 개리슨 (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