I have made a web application using tomcat that is connecting to the database and made some transactions on it, but my database oracle admin is complaining of so many connection from it and tells me that it is always cause the database to hang up due to many connection . so my question is what the best context.xml file to use and what modification should i do to mine?
my context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/applicationName">
<Resource driverClassName="oracle.jdbc.OracleDriver"
maxActive="100" maxIdle="-1" maxWait="30000" name="name" password="password"
type="javax.sql.DataSource" url="url"
username="username" />
</Context>
my Dao Class
public Dao(){
}
Context initContext;
Context envContext;
DataSource ds;
Connection conn;
public Connection getConnection() throws Exception {
initContext = new InitialContext();
envContext = (Context) initContext.lookup("java:/comp/env");
ds = (DataSource) envContext.lookup("name");
conn = ds.getConnection();
if(conn != null){
return conn;
}
return null;
}
Verify that you are closing the connection properly in the code.
Also, you should try
finally {
if(connection!= null) {
connection.close();
connection = null;
}
}
Related
I'm trying to connect a JEE app to a MySQL database. There is a lot of documentations and similar questions on this topic, but none of the solutions i've found works so far (Nonetheless, I may have miss one in particular so feel free to propose).
The server name is db and the database name is joinmyparty
Here is my java code to connect :
public class MySqlConnection {
private static Connection conn;
public static Connection getConn() {
try {
Context initContext = new InitialContext() ;
Context envContext = (Context)initContext.lookup("java:/comp/env") ;
DataSource ds = (DataSource) envContext.lookup("jdbc/joinmyparty") ;
conn = ds.getConnection();
} catch (NamingException e) {
System.out.println("Cannot get connection: " + e);
} catch (SQLException e) {
System.out.println("Cannot get connection: " + e);
}
return conn;
}
Every time I call a DAO, I use this method getConn() to open a connection and i close it in the finally block.
I wrote this into my /tomcat/conf/context.xml file :
<?xml version="1.0" encoding="UTF-8"?>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<Resource url="jdbc:mysql://db:3306/joinmyparty"
driverClassName="com.mysql.jdbc.Driver" password="mypassword"
username="myusername" maxWait="10000" maxIdle="30"
maxActive="100" type="javax.sql.DataSource" auth="Container"
name="jdbc/joinmyparty" validationQuery="select 1" testOnBorrow="true"/>
</Context>
I've tried to put the mysql-connector .jar into the /tomcat/lib or into the /WEB-INF/lib and into the build-path. I've also tried multiple versions of connectors (but only one at a time), especialy to get the one with same level as MySQL database.
When I call a servlet which requires to connect the database, I've a blank page with a POST() method and an error 5OO with a GET() method.
Here is the log error (I tried to translate it my best since i'm not english native) :
description : this server has encountered an internal error which prevents it from fulfilling your request
exception
java.lang.NullPointerException
com.picco.user.dao.UserDao.findByEmail(UserDao.java:40)
com.picco.user.servlet.Index.doGet(Index.java:56)
javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
And here the part of the code concerned (but as I said, all codes using DAO have the same problem).
try {
UserDao udao = new UserDao();
User u = udao.findByEmail(myCookieVal);
SongDao sdao = new SongDao();
ArrayList<Song> list = sdao.getAllSongs(u.getId());
Random rd = new Random();
int count = udao.count();
request.setAttribute("currentSong", list.get(rd.nextInt(list.size())));
request.setAttribute("songList", list);
request.setAttribute("partyCount", count);
this.getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);
} catch(SQLException e) {
e.printStackTrace();
} finally {
HsqlConnection.closeInstance();
}
Dont hesitate to ask me for details if I did not describe enought the problem.
Maybe the problem is that you try to fetch the resource User before having instantiated the connection that is set to null.
The MySQL JDBC JAR belongs in the Tomcat /lib folder. You want the Tomcat class loader to find it first.
Shouldn't your DAO get a connection? I'd add it to the constructor.
I'm using a Payara application server on which I have defined a connection pool in order to lookup after it in my application. The ping made from application server to database works.
In my domain.xml database resource is configured as follows:
<jdbc-resource pool-name="MasterPool" jndi-name="jdbc/master"></jdbc-resource>
<jdbc-connection-pool datasource-classname="org.apache.derby.jdbc.ClientDataSource40" name="MasterPool" res-type="javax.sql.DataSource">
...
</jdbc-connection-pool>
The setup of Context is made on servlet init method.
public void init() throws ServletException {
Context env = null;
Hashtable ht = new Hashtable();
ht.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.fscontext.RefFSContextFactory");
try {
env = new InitialContext(ht);
pool = (DataSource) env.lookup("master");
System.out.println("Data source found");
}
catch(NamingException ne) {
throw new ServletException(ne);
}
}
Can you give some insight about the message:
javax.servlet.ServletException: javax.naming.NameNotFoundException: master
I've tried to make the lookup after jdbc/master and java:/comp/env/jdbc/master
Regards,
Make sure you have below line in META-INF/context.xml
<Resource auth="Container"
driverClassName="com.mysql.jdbc.Driver"
......
name="master" // this line is important
.......
/>
I am using Tomcat version 8 and MySQL connector ver 6. Here is my context.xml:
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<Resource auth="Container"
driverClassName="com.mysql.cj.jdbc.Driver"
maxActive="20"
maxIdle="10"
maxWait="-1"
name="jdbc/MyConn"
username="root"
password="mypassword"
type="javax.sql.DataSource"
url="jdbc:mysql://localhost:3306/training_db"
/>
This is the class I use for DB connection.
public class DBConnection {
public static Connection getConnection() throws Exception{
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/MyConn");
Connection conn = ds.getConnection();
System.out.println("dbConLookp():: Data Source Connection is called."+ds.getLogWriter());
return conn;
}
}
This is what I have for connecting to database and do insertions.
try{
DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
Connection con = DBConnection.getConnection();
PreparedStatement st = con.prepareStatement("INSERT INTO EMPLOYEE (ID,FIRSTNAME,LASTNAME,MIDDLENAME,PHONENUMBER,EMAILID,ADDRESS,USERPASS) VALUES (?,?,?,?,?,?,?)");
st.setInt(1, Integer.parseInt(request.getParameter("id")));
st.setString(2, firstName);
st.setString(3, lastName);
st.setString(4, middleName);
st.setString(5, phoneNumber);
st.setString(6, emailId);
st.setString(7, address);
st.setString(8, password);
boolean rs = st.execute();
if (!rs) {
System.out.println("Record "+request.getParameter("id")+" is inserted successfully.");
} else {
System.out.println("Record is insertion is failed.");
}
st.close();
con.close();
}
catch(Exception e){
System.out.println("Exception caught:" + e);
}
On Register page, when I click register, I get java.sql.SQLException: Cannot create PoolableConnectionFactory (CLIENT_PLUGIN_AUTH is required) exception. I tried changing localhost to 127.0.0.1 but it didn't work. I also checked MySQL permissions and they look fine. I tried creating a different user but it didn't work as well. I tried moving creating another context.xml in my WEB-INF folder but no luck. I don't know what else can I do. Any help is appreciated.
In case anyone experiences the same issue, I remembered that I copied MySQL Connector JAR's into Tomcat's lib folder as suggested by a StackOverflow answer from a related question. Delete those JAR's and you'll be good to go.
I also needed to downgrade my connector version to v5.1.39. Try different connector versions if you still experiencing problems.
I have an application which is configured to connect to a specific database as per the URL with their unique credentials-
eg -
demo.mydomain.com (DB Name - demo)
client1.mydomain.com (DB Name - client1)
client2.mydomain.com (DB Name - client2)
I have defined the data source in context.xml in my web-inf dir as below -
<!-- demo Environment Configuration Starts -->
<Resource type="javax.sql.DataSource"
name="jdbc/demo"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/demo"
username="demo"
password="demo"
initialSize="10"
maxActive="100"
maxIdle="30"
minIdle="0"
suspectTimeout="60"
timeBetweenEvictionRunsMillis="30000"
minEvictableIdleTimeMillis="60000"
/>
<!-- Client1 Environment Configuration Starts -->
<Resource type="javax.sql.DataSource"
name="jdbc/client1"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/client1"
username="client1"
password="client1"
initialSize="10"
maxActive="100"
maxIdle="30"
minIdle="0"
suspectTimeout="60"
timeBetweenEvictionRunsMillis="30000"
minEvictableIdleTimeMillis="60000"
/>
The list goes on for all the available clients.
The SysServlet is defined in web.xml with a URL mapping -
<servlet>
<servlet-name>SysInfo</servlet-name>
<servlet-class>com.emsproject.action.common.SysServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SysInfo</servlet-name>
<url-pattern>/eapp/*</url-pattern>
</servlet-mapping>
public class SysServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet{
static final long serialVersionUID = 1L;
private static DataSource dataSource;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
try {
String clientName = request.getPathInfo();
String esmPool = clientName.substring(1, clientName.length()).trim();
/******************************************************
* Below code prepares the datasource by JNDI lookup *
******************************************************/
dataSource = (DataSource) new InitialContext().lookup("java:/comp/env/jdbc/"+esmPool);
} catch (Exception e) {
e.printStackTrace();
}
}
/*Returns a connection */
public Connection getConnection() throws Exception {
return dataSource.getConnection();
}
/*Closing connection when transaction is over*/
public void freeConnection(Connection dbConn) {
try {
if(null != dbConn){
dbConn.close();
}
} catch (SQLException e){
e.printStackTrace();
}
}
}
The Application is built using -
Struts 2
MySql 5
Tomcat 6
The application works fine without any issue for a single client at a time but
the problems I am facing are as below -
When a client1 performs some insert/update it is reflected to client2 & so on when application is accessed simultaneously by them.
When a Client1 performs a login (I keep certain details in session) & later Client2 logs in to the system the Client2 info is shared or visible to client1.
Simultaneous access is troubling me
Kindly suggest me a solution for the same ....
I have made few changes to the code as below while fetching a connection -
public Connection getConnection(String clientName) throws Exception {
DataSource dataSource = (DataSource) new InitialContext().lookup("java:/comp/env/jdbc/"+clientName);
return dataSource.getConnection();
}
But I have one concern regarding the statement -
DataSource dataSource = (DataSource) new InitialContext().lookup("java:/comp/env/jdbc/"+clientName);
Is it ok to initialize a DataSource every time I need a connection...
Kindly suggest...
You are not technically initializing a DataSource each time you need a connection. You are looking up the DataSource in the JNDI context each time. There will only ever be one instance of each DataSource.
The lookup is pretty fast (essentially just a map lookup) so I personally wouldn't worry too much.
What is going to be much much slower is creating the InitialContext. The creation of InitialContext() is slow and should only be done once in your application and cached.
#Pace
I am adding it as an answer to better format the code in the post I have modified,
The ctx throws a null pointer ........ (I have no idea about caching the InitialContext)
public class SysServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet{
static final long serialVersionUID = 1L;
//Context ctx = null;
InitialContext ctx = null;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
try {
ctx = new InitialContext();
String clientName = request.getPathInfo();
String esmPool = clientName.substring(1, clientName.length()).trim();
} catch (Exception e) {
e.printStackTrace();
}
}
/*Returns a connection */
public Connection getConnection(String clientName) throws Exception {
DataSource dataSource = (DataSource) ctx.lookup ("java:/comp/env/jdbc/"+clientName);
return dataSource.getConnection();
}
/*Closing connection when transaction is over*/
public void freeConnection(Connection dbConn) {
try {
if(null != dbConn){
dbConn.close();
}
} catch (SQLException e){
e.printStackTrace();
}
}
I need sugestions to avoid doing new InitialContext() on every getConnection();
I made few changes to initialize the Context only once per login & this seems to be working fine....
Only had to change the
InitialContext ctx = null;
to
private static InitialContext ctx = null;
Just construct the InitialContext during object construction of the Servlet:
public class SysServlet ....{
private InitialContext ctx = new InitialContext();
....
}
After that, you can do the look-up in the getConnection() and it should work.
This is the first time I am using SQL Server, previously I was working on MySQL and I was creating db connection pool in tomcat successfully. I am trying to use same code to create a connection pool for sql server. Please guide me where I am going wrong.
I am trying login as Windows Authentication, I have copied sqljdbc_auth.dll in tomcat bin directory.
Following is the code I wrote in my context.xml file under META-INF:
Context antiJARLocking="true" path="">
<Resource
auth="Container"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
logAbandoned="true"
maxActive="100"
maxIdle="30"
maxWait="1000"
name="jdbc/mydb"
removeAbandoned="true"
removeAbandonedTimeout="60"
type="javax.sql.DataSource"
url="jdbc:sqlserver://localhost;integratedSecurity=true;" />
</Context>
And below is the java class which is providing connections:
public class ConnectionPool {
private static ConnectionPool pool=null;
private static DataSource dataSource = null;
public synchronized static ConnectionPool getInstance(){
if (pool == null){
pool = new ConnectionPool();
}
return pool;
}
private ConnectionPool(){
try{
InitialContext ic = new InitialContext();
dataSource = (DataSource) ic.lookup("java:/comp/env/jdbc/mydb");
}
catch(Exception e){
System.out.println(e);
}
}
public Connection getConnection(){
try{
return dataSource.getConnection();
}
catch (SQLException sqle){
System.err.println(sqle);
return null;
}
}
public void freeConnection(Connection c){
try{
c.close();
}
catch (SQLException sqle){
System.err.println(sqle);
}
}
}
When I tried calling getConnection() then I got following exception:
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
Exception in thread "main" java.lang.NullPointerException
at ConnectionPool.getConnection(ConnectionPool.java:39)