Warning: New to Java
I have a simple Netbeans project - I wanted to just learn about interacting with DB's coming from php I thought I would have a go with a local one running on my computer.
Lots of the examples out there say to use the InitialContext() object to refer to the database resource.
After following the examples I get the following exception - Lots of Google stuff points to some .xml file - which I have no idea about or even where it exists in the Netbeans project? I'm not using a Webserver at this time so not Tomcat or anything like that, just local Java program to do this, I suspect this might be the problem. Could anyone shed some light on this?
Exception thrown 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.
package learningjava;
import com.mysql.jdbc.jdbc2.optional.*;
import com.mysql.jdbc.Driver;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.*;
public class LearningJava {
public static void main(String[] args) {
MysqlDataSource test_db = new MysqlDataSource();
test_db.setServerName("localhost");
test_db.setDatabaseName("dev");
try {
InitialContext test_db_context = new InitialContext();
test_db_context.bind("jcdb/testdb", test_db);
MysqlDataSource test_db_datasource = (MysqlDataSource)test_db_context.lookup("testdb");
} catch (NamingException e) {
System.out.println("Exception thrown " + e);
}
try {
test_db.getConnection("root","password");
} catch (SQLException e) {
System.out.println("Exception thrown " + e);
}
}
}
could you try to add this before the InitialContext test_db_context = new InitialContext();:
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory");
System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming");
You should include the jar naming-common-4.1.34 and mysql-connector-java-5.1.6 in your classpath
This example works for me (not optimized but works!)
public static void main(String[] args) throws NamingException {
// Create initial context
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory");
System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming");
InitialContext ic = new InitialContext();
ic.createSubcontext("java:");
ic.createSubcontext("java:comp");
ic.createSubcontext("java:comp/env");
ic.createSubcontext("java:comp/env/jdbc");
MysqlConnectionPoolDataSource mysqlConnectionPoolDataSource = new MysqlConnectionPoolDataSource();
mysqlConnectionPoolDataSource.setUser("root");
mysqlConnectionPoolDataSource.setPassword("root");
mysqlConnectionPoolDataSource.setURL("jdbc:mysql://localhost:3306/test_my_database");
ic.bind("java:comp/env/jdbc/test", mysqlConnectionPoolDataSource);
}
In general you should understand that JNDI should have a server. In a code snippet you've provided you're using a _CLIENT_SIDE_ part of JNDI technology when you're doing your lookup. There should be a JNDI server that should be accessible from your local client connection.
Once configured properly, the call to lookup should issue a connection with JNDI server and provide a way to obtain/bind resources to that server.
How to configure JNDI properly?
Usually you should supply a properties file that will contain a host name of this server, a port + some implementation specific information.
JNDI server is usually already provided when you're using application server (like JBoss or Web Sphere).
I think this is the root of misunderstanding here.
Hope, this helps
Usually JNDI is used inside an application server which is not your case.
For your needs you may use the following code:
Class.forName("com.mysql.jdbc.Driver")
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/dbname", "user", "password");
Also you need to download MySQL driver here and add corresponding JAR file (mysql-connector-java-5.1.21-bin.jar) to your application's class path here is described how to do it.
Related
I'm trying to understand establishing a database-connection with a DataSource Object and the JNDI API.
I'm working with Intellij UE and have a local Tomcat-8- and Postgres-Server running.
I proceed as mentioned in the Oracle Java Documentation:
Creating Instance of DataSource Class and Setting its Properties
org.postgresql.ds.PGSimpleDataSource dataSource = new org.postgresql.ds.PGSimpleDataSource();
dataSource.setServerName("localhost");
dataSource.setDatabaseName("db01");
dataSource.setUser("jwi");
dataSource.setPassword("password");
Registering DataSource Object with Naming Service That Uses JNDI API
Context ctx = null;
try {
ctx = new InitialContext();
ctx.bind("jdbc/localDB", dataSource);
} catch (NamingException e) {
e.printStackTrace();
}
The Oracle Documentation says:
With the properties set, the system administrator can register the BasicDataSource object with a JNDI (Java Naming and Directory Interface) naming service.
So my first Question is: What means to register a DataSource? Is my code obove already the registration of an DataSource Object to JNDI?
Using Deployed DataSource Object
try {
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("jdbc/localDB");
dbCon = ds.getConnection();
...
In this code cutting IntelliJ always claims, that it can't resolve the method getConnection().
The Oracle Documentation says:
After a basic DataSource implementation is deployed by a system administrator, it is ready for a programmer to use.
So my second Question is: What exactly means deployed in this case? Creating a DataSource Instance and execute the registration with JDNI? Or does deployed mean the Tomcat context.xml and web.xml configuration (Tomcat 8 JNDI How-To)?
I'd really appreciate if anybody has a good step by step instruction for this issue, in fact that the Oracle Documentation isn't really clear about some points imho.
for the second question, deployed means that your datasource is declared in the context.xml in tomcat.
Here is an example of an oracle database (you have to change the driver for postgres) :
<Resource name="jdbc/myoracle" auth="Container"
type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#127.0.0.1:1521:mysid"
username="scott" password="tiger" maxTotal="20" maxIdle="10"
maxWaitMillis="-1"/>
After that, you can code the java part, for that you can watch this link http://www.javapractices.com/topic/TopicAction.do?Id=127
For a complete example, there's a good tutorial here http://alvinalexander.com/blog/post/java/how-configure-tomcat-dbcp-connection-pool-pooling-postgres.
Hope this help
I have a simple problem, I have a Stateless EJB bean running in Glassfish 4. I have a client, and I want to lookup for this ejb, and I simply cannot make the right name. How should I name these correctly to work?
I just got javax.naming.NamingException, but I have no clue how to do it right.
I follow the java:global/[ear-name]/[jar-name]/[ejb-name]![fully-qualified-interface-name] convention.
Here is the client:
...
public class Main {
public static void main(String[] args) {
Calculator calculator;
Context ctx = null;
try {
Properties environment = new Properties();
environment.setProperty("org.omg.CORBA.ORBInitialHost", "127.0.0.1");
environment.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
// Find the EJB with a JNDI lookup
ctx = new InitialContext(environment);
calculator = (Calculator)ctx.lookup(
"java:global/calculator-application/calculator-ejb/calcBean!eak.Calculator"
);
} catch(NamingException ex) {
ex.printStackTrace();
return;
}
...
}
}
Here are the annotations of my EJB component:
#Stateless(name="calcBean", mappedName="calc")
#Remote(Calculator.class)
public class CalculatorBean implements Calculator {
...
And I run what jndi names are in my Glassfish server:
C:\javaee\glassfish4\glassfish\bin>asadmin.bat list-jndi-entries
UserTransaction: com.sun.enterprise.transaction.startup.TransactionLifecycleServ
ice$2
ejb: com.sun.enterprise.naming.impl.TransientContext
java:global: com.sun.enterprise.naming.impl.TransientContext
calc__3_x_Internal_RemoteBusinessHome__: javax.naming.Reference
calc: javax.naming.Reference
jdbc: com.sun.enterprise.naming.impl.TransientContext
concurrent: com.sun.enterprise.naming.impl.TransientContext
com.sun.enterprise.container.common.spi.util.InjectionManager: com.sun.enterpris
e.container.common.impl.util.InjectionManagerImpl
jms: com.sun.enterprise.naming.impl.TransientContext
calc#eak.Calculator: javax.naming.Reference
Command list-jndi-entries executed successfully.
You'r configuration looks valid to me. I tested your example and it worked just fine. Please make sure that the gf-client.jar from glassfish4/glassfish/lib is in your classpath. Please also confirm that your application, module and bean names are as you see in the Glassfish console. In my case JNDI lookup string java:global/ear-1.0-SNAPSHOT/my-ejb-jar-1.0-SNAPSHOT/calcBean!Echo worked perfectly.
I'm trying to connect to EJB on WebSphere 7.0. The EJB requires javax.ejb.SessionContext and reads Principal from it, so I need to log in before calling it.
I'm using the following code in stand-alone application:
import javax.naming.InitialContext;
import javax.security.auth.login.LoginContext;
import com.ibm.websphere.security.auth.WSSubject;
import com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl;
public static void main(String[] args) throws Exception {
InitialContext ic = new InitialContext(System.getProperties());
LoginContext lc = new LoginContext("WSLogin",
new WSCallbackHandlerImpl("myuser","mypass"));
lc.login();
WSSubject.setRunAsSubject(lc.getSubject());
SessionContext sessionContext=(SessionContext) ic.lookup(
"java:comp/env/sessionContext");
}
I've added the entry to my jmxremote.access:
myuser readwrite
However, I get an exception:
Caused by: javax.naming.ConfigurationException: Name space accessor
for the java: name space has not been set. Possible cause is that the
user is specifying a java: URL name in a JNDI Context method call but
is not running in a J2EE client or server environment. at
com.ibm.ws.naming.java.javaURLContextFactory.isNameSpaceAccessable(javaURLContextFactory.java:98)
at
com.ibm.ws.naming.urlbase.UrlContextFactory.getObjectInstance(UrlContextFactory.java:82)
at
javax.naming.spi.NamingManager.getURLObject(NamingManager.java:584)
at
javax.naming.spi.NamingManager.getURLContext(NamingManager.java:533)
at
javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:320)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
What else should I do, to run my code in the 'J2EE client environment' mentionend in the error message?
In order to use java:comp, you would need to package the client application in an .ear and use launchClient. Ultimately, that's just going to use -CCBootstrapHost/-CCBootstrapPort (or defaults) to connect to the target server to look up the EJB, so you could just use the EJB thinclient and use the fully-qualified EJB binding name instead (see the CNTR0167I messages in SystemOut.log).
you'll need to use the WAS client runtime JARs. WAS_HOME/AppServer/runtimes. You will need the ORB and the other service specific JARs. As an alternative to using launchClient, you can manually specify the context factory you'll be using here:
InitialContext ic = new InitialContext(System.getProperties());
set the
java.naming.factory.initial
variable (in your system env or in a Properties object) to
com.ibm.websphere.naming.WsnInitialContextFactory`
I have configured MysqlDataSource in tomcat using this link.I have written junit test cases.when am i calling below connection from junit it throws following errors.
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
I have used following code
class DataConnection {
private static DataSource dataSource;
public DataConnection() {
try {
Context ctx = new InitialContext();
dataSource = (DataSource)ctx.lookup("java:comp/env/jdbc/test");
} catch (NamingException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
new DataConnection();
Connection con=dataSource.getConnection();
return con;
}
}
How to call tomcat from junit? How to achieve this?
The code you give gets the database connection from JNDI, e.g. when running in tomcat from the container. However, for Unit Tests (assuming that's what you use JUnit for) I'd rather suggest to use "dependency injection" - e.g. explicitly pass a database connection to the code under test or manually set it up before the test runs.
There's no need to rely on JNDI for executing your tests: That's not what you want to test, instead, you want to just verify that your actual code is running correctly.
You don't need any fancy library (e.g. spring) for dependency injection, just a slightly adjusted architecture. This will greatly enhance the testability of your application and lower the execution time of your tests.
(This is based on my assumptions of your situation based on the little bit of information that you give in your question)
Give TomcatJNDI a try. It is based on embedded Tomcat but initializes only Tomcat's JNDI environment without starting a server. So you can access all your resources as configured in Tomcat's configuration files in tests or from within any Java SE application. The API is simple. For instance to get a DataSource declared in context.xml:
TomcatJNDI tomcatJNDI = new TomcatJNDI();
tomcatJNDI.processContextXml(contextXmlFile);
tomcatJNDI.start();
Then you can lookup the DataSource as usual
DataSource ds = (DataSource) InitialContext.doLookup("java:comp/env/path/to/datasource")
More information about TomcatJNDI can be found here.
Here's the class
package db;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author Oshadha Gunawardena
*/
public class DBFacade {
private static Connection c;
public static void connect() throws Exception {
if (c == null) {
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("props.xml");
prop.loadFromXML(fis);
String dbUrl = prop.getProperty("dburl");
String dbDriver = prop.getProperty("dbdriver");
String dbUser = prop.getProperty("username");
String dbPass = prop.getProperty("password");
Class.forName(dbDriver).newInstance();
c = DriverManager.getConnection(dbUrl, dbUser, dbPass);
}
}
public static ResultSet fetch(String sql) throws Exception {
connect();
synchronized (c) {
return c.createStatement().executeQuery(sql);
}
}
public static void save(String sql) throws Exception {
connect();
synchronized (c) {
c.createStatement().executeUpdate(sql);
}
}
}
I'm using this class as my database facade class,so my entire project is a web application I'm calling this fetch and save methods using a servlet, but when I try to run this It throws an exception (java.io.FileNotFoundException). All the paths are set correctly props.xml file is in my project home directory also it works when I try to print the data to the out put.
String dbUrl = prop.getProperty("dburl")
System.out.println(dbUrl);
Problem only occurs when I try to deploy and run the project.
Note: I'm using NetBeans 6.1 as my primary IDE.
Thanks
If you are loading from war file , you should be using
getClass().getResourceAsStream("props.xml");
As J-16 SDiZ says, your file is probably ending up in the war file - or if it's not, then your working directory probably isn't what you think it is.
You say that props.xml is in the "project home directory" - where is it after deployment? Is it in a war file (in which case you'll need to use getResourceAsStream(), although I suspect that Class.getClassLoader().getResourceAsStream("props.xml") is more likely to work:
InputStream input = null;
try
{
input YourClassName.class.getClassLoader.getResourceAsStream("props.xml");
if (input == null)
{
// Throw an appropriate exception here to show you can't find your file
}
prop.loadFromXML(input);
}
finally
{
if (input != null)
{
input.close();
}
}
If it really is a file, you'll need to find some way of working out the directory it's in programmatically, then use:
File file = new File(directory, "props.xml");
FileInputStream fis = new FileInputStream(file);
// And close it in a finally block as above
If you used the getResourceAsStream method, then your property file must be on the classpath. See the documentation for your servlet container to see what it sets the classpath to.
However, since we are talking about JDBC connections, this isn't the right approach to use. The preferred mechanism for obtaining connections is using a DataSource.
Instructions for configuring a DataSource in Tomcat can be found here
Using a DataSource object is the preferred alternative to using the DriverManager for establishing a connection to a data source. They are similar to the extent that the DriverManager class and DataSource interface both have methods for creating a connection, methods for getting and setting a timeout limit for making a connection, and methods for getting and setting a stream for logging.
Their differences are more significant than their similarities, however. Unlike the DriverManager, a DataSource object has properties that identify and describe the data source it represents. Also, a DataSource object works with a JavaTM Naming and Directory InterfaceTM (JNDI) naming service and is created, deployed, and managed separately from the applications that use it. A driver vendor will provide a class that is a basic implementation of the DataSource interface as part of its JDBC 2.0 or 3.0 driver product. What a system administrator does to register a DataSource object with a JNDI naming service and what an application does to get a connection to a data source using a DataSource object registered with a JNDI naming service are described later in this chapter.
Being registered with a JNDI naming service gives a DataSource object two major advantages over the DriverManager. First, an application does not need to hardcode driver information, as it does with the DriverManager. A programmer can choose a logical name for the data source and register the logical name with a JNDI naming service. The application uses the logical name, and the JNDI naming service will supply the DataSource object associated with the logical name. The DataSource object can then be used to create a connection to the data source it represents.
The second major advantage is that the DataSource facility allows developers to implement a DataSource class to take advantage of features like connection pooling and distributed transactions. Connection pooling can increase performance dramatically by reusing connections rather than creating a new physical connection each time a connection is requested. The ability to use distributed transactions enables an application to do the heavy duty database work of large enterprises.