2013-12-03 2 views
18

Ich benutze ein JNDI zum Erstellen von Tomcat Connection Pool. Es funktioniert gut in einer Webanwendung. Ich glaube, der InitialContext wird vom Tomcat-Server bereitgestellt.Initialkontext in einem eigenständigen Java-Programm

Aber wenn ich versuche, dasselbe Dienstprogramm von einem eigenständigen Java-Programm aufzurufen, ist das initContext-Objekt null. Wie kann ich explizit alle erforderlichen Eigenschaften bereitstellen, die das Kontextobjekt erwartet?

Fehler: javax.naming.NoInitialContextException: Need Klasse Namen in Umgebung oder Systemeigenschaft angeben, oder als Applet Parameter oder in einer Anwendungsressourcendatei: java.naming.factory.initial

Antwort

5

Sie können auch Ihren eigenen benutzerdefinierten Kontext erstellen.

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

Weitere Details finden Sie unter Running Beans Locally that use Application Server Data Sources.


newUPDATE

können Sie die Klasse org.springframework.mock.jndi.SimpleNamingContextBuilder des Frühlings nutzen. zB:

  • Setup:

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

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

Bitte beachten Sie, wie die letzten Kommentare des Artikels Sie verknüpft darauf hingewiesen, dass die Lösungen fehlerhaft ist: Ein Stackoverflow wird während der Lookup geworfen, wenn der Name null ist oder nicht gefunden ... – Lonzak

+0

Hey, @Lonzak Ich habe ein Update. –

0

Tomcat bietet Kontext & DataSource-Implementierungen, die mit der InitialContext-Klasse arbeiten. Wenn Sie Tomcat ausführen, wird die Eigenschaft Context.INITIAL_CONTEXT_FACTORY so eingestellt, dass sie auf Tomcat-Implementierungen zeigt. Wenn Sie Tomcat nicht verwenden, haben Sie diese Fähigkeit nicht ... Sie müssen eine Drittanbieter-Bibliothek wie c3p0 für das Verbindungs-Pooling verwenden.

1

Es gibt keine Möglichkeit, die Tomcat Context Factory direkt zu verwenden, siehe here für ein wenig mehr Dokumentation zu den Alternativen. Aber ich empfehle Sie versuchen, eine Registrierung außerhalb von Tomcat laufen ...

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

Sie könnten Ihren Code in Tomcat ändern auch diese externe RegistryContext zu verwenden und dann beide (e) die gleichen JNDI Provider wären. Diese question scheint sehr ähnlich.

17

Hier ist ein Beispiel aus der akzeptierten Antwort angepasst aber Inline tut alles zu vermeiden, Erstellen von zusätzlichen Klassen.

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

Herzlichen Glückwunsch! Optimale Lösung, sauber und einfach! –

+2

Ein Vorschlag für eine großartige Inline-Lösung :-) – janhink

+2

Das hat mir Stunden beim Durchforsten der Java-APIs erspart. Vielen Dank! –

Verwandte Themen