web-dev-qa-db-fra.com

Contexte initial dans un programme Java autonome

J'utilise un JNDI pour créer un pool de connexions Tomcat. Cela fonctionne très bien dans une application Web. Je crois que le InitialContext est fourni par le serveur Tomcat.

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

Mais lorsque j'essaie d'appeler le même utilitaire à partir d'un programme Java autonome, l'objet initContext est null. Comment puis-je explicitement fournir toutes les propriétés nécessaires que l'objet Context attend.

Erreur: javax.naming.NoInitialContextException: nécessité de spécifier la classe name dans la propriété environment ou system, ou en tant que paramètre d'applet, ou dans un fichier de ressources d'application: Java.naming.factory.initial

19
Satish Jonnala

Vous pouvez également créer votre propre contexte personnalisé. 

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

Voir Exécution locale de beans utilisant des sources de données du serveur d'applications pour plus de détails.


new METTRE À JOUR

Vous pouvez utiliser la classe org.springframework.mock.jndi.SimpleNamingContextBuilder de Spring. par exemple.:

  • Installer:

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

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

Voici un exemple adapté de la réponse acceptée mais faisant tout en ligne pour éviter de créer des classes supplémentaires.

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

Il n’existe pas de moyen d’utiliser directement Tomcat Context Factory, voir ici pour un peu plus de documentation sur les alternatives. Mais je vous recommande d’essayer d’exécuter un registre en dehors de 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);

Vous pouvez modifier votre code dans Tomcat pour qu'il utilise également ce RegistryContext externe, puis les deux ensembles utiliseraient le même fournisseur JNDI. Cette question semble très similaire.

1
Elliott Frisch

Tomcat fournit des implémentations de Context & DataSource qui fonctionnent avec la classe InitialContext. Lors de l'exécution de Tomcat, la propriété Context.INITIAL_CONTEXT_FACTORY est définie pour pointer vers les implémentations de Tomcat. Si vous n’exécutez pas Tomcat, vous n’avez pas cette possibilité ... vous devez utiliser une bibliothèque tierce telle que c3p0 pour le regroupement des connexions.

0
ClickerMonkey

Vous pouvez créer un contexte initial à l'aide du code de coup.

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

si vous voulez créer un contexte initial personnalisé, vous pouvez étendre la classe javax.naming.InitailContext

0
faizan saifi