I have JNDI config for all possible database connectivity in my application. Meanwhile I am using JUNIT to test my applications. I find successful connection form my webservices class invocation but error throws while calling it through junit test class.
My JNDI setting is
public static Connection getConnectionPool() {
Connection conn = null;
System.out.println("Creating connection pool.");
try {
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup(getJNDIName());
conn = ds.getConnection();
} catch (SQLException e1) {
e1.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
}
return conn;
}
private static String getJNDIName()
{
if(!readJNDI)
{
try{
Properties prop = new Properties();
prop.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("config.properties"));
JNDIName = prop.getProperty("jndi.name");
System.out.println("JNDIName : "+JNDIName);
readJNDI = true;
}catch(Exception ex){
ex.printStackTrace();
}
}
return JNDIName;
}
Below mentioned is the 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
How do I resolve it.?
Thanks in advance.
You should use a local datasource.
Just pull out the DataSource/TransactionManager definition into a separate XML file, and use that instead of the JNDI one during testing.
You can still use all the rest of your configuration.
Related
So i am facing the following problem.
I have developed an web app that has the following connection to a SQL Server database. (db connection code attached)
public class DBConnection
{
private DatabaseMetaData dma;
private static Connection con;
private static DBConnection instance = null;
private static String security = "integratedSecurity=true;";
private DBConnection()
{
try {
Class.forName("net.sourceforge.jtds.jdbc.Driver");
} catch (Exception e) {
System.out.println("Can not find the driver");
System.out.println(e.getMessage());
}
try{
con = DriverManager.getConnection("jdbc:jtds:sqlserver://<Machine>;databaseName=<DBName>; useNTLMv2=true;");
//set autocommit
con.setAutoCommit(true);
dma = con.getMetaData(); // get meta data
System.out.println("Connection to " + dma.getURL());
System.out.println("Driver " + dma.getDriverName());
System.out.println("Database product name " + dma.getDatabaseProductName());
}
catch(Exception e){
System.out.println("Problems with the connection to the database");
System.out.println(e.getMessage());
System.out.println(con);
}
}
public static void closeConnection()
{
try{
con.close();
System.out.println("The connection is closed");
}
catch (Exception e){
System.out.println("Error trying to close the database " + e.getMessage());
}
}
public Connection getDBcon()
{
return con;
}
public static DBConnection getInstance()
{
if (instance == null)
{
instance = new DBConnection();
}
return instance;
}
public static void startTransaction()
{ try{
con.setAutoCommit(false);
}
catch(Exception e){
System.out.println("fail start transaction");
System.out.println(e.getMessage());
}
}
public static void commitTransaction()
{ try{
con.setAutoCommit(true);
}
catch(Exception e){
System.out.println("fail commit transaction");
System.out.println(e.getMessage());
}
}
public static void rollbackTransaction()
{
try
{
con.rollback();
con.setAutoCommit(true);
}
catch(Exception e){
System.out.println("fail rollback transaction");
System.out.println(e.getMessage());
}
}
I am using a Tomcat 8 on InteliJ IDE for running the app and debugging. Which works fine. (DB connection is established)
The problem is that when i take the war file and deploy it in the same Tomcat Server i get no DB Connection. (No DB connection)
I have checked all the .jar files in the tomcat and the project and I have added all the needed files.
Can't seem to find what is causing this issue. Maybe there is someone who got stuck with the same issue
I can't get a proper undertanding what is causing this issue and how to fix it
**EDIT: Following I have added the error displayed when trying to load data
type Exception report
message Request processing failed; nested exception is java.lang.NullPointerException
description The server encountered an internal error that prevented it from fulfilling this request.
exception
org.springframework.web.util.NestedServletException: Request
processing failed; nested exception is java.lang.NullPointerException
root cause
java.lang.NullPointerException
com.lifeletapp.business.dataLayer.DbLogIn.isValidUser(DbLogIn.java:27)
com.lifeletapp.business.HelloController.verifyLogin(HelloController.java:33)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
DbLogin class:
public class DbLogIn implements ILogIn
{
private Connection conn;
public DbLogIn()
{
conn = DBConnection.getInstance().getDBcon();
}
public Staff isValidUser(String userName, String password)
{
Staff staff = new Staff();
try {
String query = "SELECT * FROM Staff WHERE userName=? AND pass=?";
PreparedStatement preparedStatement = conn.prepareStatement( query );
preparedStatement.setString(1, userName);
preparedStatement.setString(2, password);
ResultSet resultSet = preparedStatement.executeQuery();
while( resultSet.next() ) {
staff.setUserID(resultSet.getInt("userID"));
staff.setfName(resultSet.getString("fName") );
staff.setlName(resultSet.getString("lName") );
staff.setUserName(resultSet.getString("userName") );
staff.setPass(resultSet.getString("pass") );
staff.setEmail(resultSet.getString("email") );
}
resultSet.close();
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
return staff;
}
}
This is more a config or server issue. Not a code issue.
As mentioned in the comments I have tested if var conn == null -> resulted true. And the connection dose not get nulled anywhere. Please view code. Then again the above code works when run from the InteliJ debugger.
So finally figured out what was the issue.
Why was it working on my IDE config:
1. I was using java JDK 1.7 as JAVA_HOME
2. I was using an older version of Tomcat as a build
3. In order to work with JDTS you need to extract the nlmauth.dll from the .jar archive and copy it to the configured env JDK(jdk1.7-->>bin->>copy here)
Why was it not working on Tomcat server:
1.I was using Tomcat 8.xxx
2.Tomcat 8.xx require JDk 8
3. In the JDK 8 i have not past the nlmauth.dll ( once i have done this everything was working)
In order to approach this issue the first clue will be looking into the tomcat server logs.
On my presumption this issue is prom to occur only when you have an Database connection establish via Integrated Security.
My presumption is related to the fact that in the tomcat log the main error that was denying the JDBC driver was based on the integrated security credentials.
Best of luck to you all out there.
I have a Servlet which initializes its DataSource in the Servlets init method (because it is accessed there the first time). When the servlet is getting loaded I get the following exception message
Cannot create JDBC driver of class '' for connect URL 'null'
But when the first request is processed the jndi lookup works fine and the DataSource is initialized properly.
Here is my DataSource class:
public class PostgresDataSource{
private static DataSource dataSource;
static {
try {
dataSource = (DataSource) new InitialContext().lookup("java:/comp/env/jdbc/somedb");
} catch (NamingException e) {
Log.logger.fatal("Failed to initialize DB!");
Log.logger.error(e.getMessage());
e.printStackTrace();
}
}
public static Connection checkOut(){
if ( dataSource != null )
{
try {
return dataSource.getConnection();
} catch (SQLException e) {
Log.logger.error("Failed to establish DB connection!");
Log.logger.error(e.getMessage());
e.printStackTrace();
return null;
}
}
else
{
Log.logger.error("Failed to check out DB-Connection: Postgres DataSource not initialized!");
return null;
}
}
public static void checkIn( Connection dbcon){
if ( dataSource != null )
{
try {
dbcon.close();
} catch (SQLException e) {
Log.logger.error("Failed to close DB connection!");
e.printStackTrace();
}
}
else
{
Log.logger.error("Cannot check in DB-Connection: Postgres DataSource not initialized!");
}
}
}
Anyone encountered the same problem? What's the reason for this and how to solve it?
Instead of using
dataSource = (DataSource) new InitialContext().lookup("java:/comp/env/jdbc/somedb");
Please use the following, this may solve the problem
InitialContext context = new InitialContext();
Context envCtx = (Context) context.lookup("java:comp/env");
dataSource = (DataSource) envCtx.lookup("jdbc/somedb");
I have read this page: http://www.javaranch.com/journal/200601/JDBCConnectionPooling.html
The approach of Method Scope Connections seems quite good for me.
But i have one Question, when do i init the JDBCServlet class?
Every time i want a connection? Because i thought that everytime i want a connection i just call getConnection()...
public class JDBCServlet extends HttpServlet {
private DataSource datasource;
public void init(ServletConfig config) throws ServletException {
try {
// Look up the JNDI data source only once at init time
Context envCtx = (Context) new InitialContext().lookup("java:comp/env");
datasource = (DataSource) envCtx.lookup("jdbc/MyDataSource");
}
catch (NamingException e) {
e.printStackTrace();
}
}
private Connection getConnection() throws SQLException {
return datasource.getConnection();
}
public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException {
Connection connection=null;
try {
connection = getConnection();
..<do JDBC work>..
}
catch (SQLException sqlException) {
sqlException.printStackTrace();
}
finally {
if (connection != null)
try {connection.close();} catch (SQLException e) {}
}
}
}
}
The JDBCServlet servlet is invoked when you navigate to a link where the servlet is mapped to.
So you dont have to do anything apart apart from the mapping from URL to servlet which is done in the web.xml.
the web container then create the instance of the servlet by using init method and then call doGet.
This is a PDF for a servlet tutorial with tomcat, but the basics are the same.
http://www.tutorialspoint.com/servlets/servlets_tutorial.pdf
look at the servlet deployment section
for the DBUtil Class this is a good example.
public class DBUtil {
private static DataSource dataSource;
static {
try {
dataSource = new InitialContext().lookup("jdbc/MyDataSource");
} catch (NamingException e) {
throw new ExceptionInInitializerError("'jdbc/MyDataSource' not found in JNDI", e);
}
}
public static Connection getConnection() {
return dataSource.getConnection();
}
}
This gives your class that can be used by all servlets in your Web Application.
you wil call the DBUtil class by
try {
connection = DBUtil.getConnection();
statement = connection.prepareStatement("SELECT id, foo, bar FROM table");
resultSet = statement.executeQuery();
//Do what you need to do.
} finally {
if (resultSet != null) try { resultSet.close(); } catch (SQLException ignore) {}
if (statement != null) try { statement.close(); } catch (SQLException ignore) {}
if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
}
Servlets are initialised by the Container which will call init as required and defined by the web.xml configuration file.
Use the Apache Tomcat JDBC Connection pools which does the same in a standard way.
There's many connection pooling libraries including MySQL's own. Many people use C3P0 which is very mature.
The common idea is that you define the Datasource in the server container and access the JNDI reference from your code. During the servlet init you're just looking up the datasource so this is the ideal place to do this. This will not use any connections until you actually perform an action.
See Tomcat DBCP for a good intro and if you wish to use C3P0 C3P0 Tomcat Configuration
I need to initialize a DataSource given url and driver.
Its need to be generic enough to support Oracle and SQL Server.
the app is running on jboss 5.
provided sample for both:
<db-connection name="TEST-ORACLE">
<url>jdbc:oracle:thin:#test:1521:ins1</url>
<driver>oracle.jdbc.xa.client.OracleXADataSource</driver>
<user>user</user>
<password>{ENCR}oRloKFKlqXs=</password>
<min-size>5</min-size>
<max-size>30</max-size>
<idle-timeout-minutes>1</idle-timeout-minutes>
</db-connection>
<db-connections>
<db-connection name="TEST-MSSQLSERVER">
<url>jdbc:jtds:sqlserver://server:1433/db;ProgramName=program;SelectMethod=cursor;useLOBs=false</url>
<driver>net.sourceforge.jtds.jdbc.Driver</driver>
<user>user</user>
<password>{ENCR}oRloKFKlqXs=</password>
<min-size>40</min-size>
<max-size>80</max-size>
<idle-timeout-minutes>1</idle-timeout-minutes>
</db-connection>
The OracleXADataSource is implementing the inteface DataSource so its quit easy... but im not sure that generic enough.
EDIT
I wonder what should be the way to achive that if i have multipile db connections and multipile instances / schemas in those connections.....
my current code looks like:
private DataSource getDataSourceForTanent(TenantConfig i_Tenant) {
DataSource result = null;
ClassLoader loader = DBConnector.class.getClassLoader();
try {
Class driverClass = loader.loadClass(i_Tenant.getDriver());
Object driver = driverClass.newInstance();
if(driver instanceof OracleDataSource){
((OracleDataSource)driver).setURL(i_Tenant.getUrl());
((OracleDataSource)driver).setUser(i_Tenant.getUser());
((OracleDataSource)driver).setPassword(i_Tenant.getPassword());
result = (DataSource) driver;
} else if(driver instanceof Driver){
Properties prop = new Properties();
prop.put("user", i_Tenant.getUser());
prop.put("password", i_Tenant.getPassword());
prop.put("min-size", i_Tenant.getMinSize());
prop.put("max-size", i_Tenant.getMaxSize());
prop.put("idle-timeout-minutes", i_Tenant.getIdleTimeoutMinute());
Connection con = ((Driver)driver).connect(i_Tenant.getUrl(), prop);
if(con != null){
//TODO: SQLServer handling
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
TenantConfig is a java bean holding the xml properties.
Here's a generic code snippet to get a DataSource by JNDI name:
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/mydatasource");
But from your XML file I am not sure what the JNDI name is. What XML dialect is it?
How to connect data base using jndi datasource in weblogic. i am using following code but it is giving null value for connection
Context ctx = null;
Hashtable evn = new Hashtable();
evn.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
evn.put(Context.PROVIDER_URL,"t3://localhost:7001");
Connection conn = null;
try {
ctx = new InitialContext(evn);
javax.sql.DataSource ds
= (javax.sql.DataSource) ctx.lookup ("mydatasource");
conn = ds.getConnection();
}catch (Exception e) {
System.out.println();
// TODO: handle exception
}
Append this to clarify more about exception reason
catch(Exception sqlExp)
{
throw new SQLException("getConnection :: Exception"+sqlExp);
}
post the exception as suggested by Stano
on weblogic console test the connection
http://docs.oracle.com/cd/E23943_01/web.1111/e13737/jdbc_datasources.htm#CHDIIFHH
did you target the datasource to weblogic server where the application works?
//try this code:
Connection con = null;
DataSource datasource = null;
Context initialContext = new InitialContext();
// "jdbc/MyDBname" >> is a JNDI Name of DataSource on weblogic
datasource = (DataSource) initialContext.lookup("jdbc/MyDBname");
con = datasource.getConnection();