I'm using a JNDI for creating connection pool. It works great in a web application. I believe the InitialContext is provided by the tomcat server.
Context initContext = new InitialContext(); Context envContext = (Context)initContext.lookup("java:/comp/env"); dataSource = (DataSource)envContext.lookup("jdbc/testdb");
But when I try to call the same utility from a standalone Java program, the initContext object is null. How can I explicitly provide all the necessary properties that Context object is expecting.
Error : javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
The initial context implements the Context interface and provides the starting point for resolution of names. When the initial context is constructed, its environment is initialized with properties defined in the environment parameter passed to the constructor, and in any application resource files.
JNDI, part of the J2EE specification, provides naming and directory functionality for Java applications. Because JNDI is defined independently of any specific naming or directory service implementation, it enables Java applications to access different naming and directory services using a single API.
InitialContext ic = new InitialContext(); Object obj = ic. lookup(); If name is empty, returns a new instance of this context (which represents the same naming context as this context, but its environment may be modified independently and it may be accessed concurrently).
The Java Naming and Directory Interface (JNDI) is a Java API for a directory service that allows Java software clients to discover and look up data and resources (in the form of Java objects) via a name. Like all Java APIs that interface with host systems, JNDI is independent of the underlying implementation.
Here is an example adapted from the accepted answer but doing everything inline to avoid creating extra classes.
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(); } }
You could also create your own custom context.
LocalContext ctx = LocalContextFactory.createLocalContext(); ctx.addDataSource("jdbc/testdb", driverName, url, usr, pwd);
See Running Beans Locally that use Application Server Data Sources for more details.
UPDATE
You can use the class org.springframework.mock.jndi.SimpleNamingContextBuilder
of Spring. e.g.:
Setup:
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); builder.bind("jdbc/Oracle", ods); builder.activate();
Use:
DataSource ds = InitialContext.doLookup("jdbc/Oracle");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With