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.
Related
I'm trying to figure out how to connect to oracle database remotely, in order to fetch information/data from it. I don't know the steps on how to go about it. I would also like to use datasource to connect with the oracle DB. I'm completely new to this, and if its not too much to ask can I get step by steps on how to do this. I'm using liberty server.
All I have done is read through the internet for something that answers my query but i just cant seem to find what I'm looking for. Below is what I have and I'm trying to see how to achieve my goal from what I have.
In this scenario I want to use datasource and connect remotely with oracle DB.
package com.dBconnect;
import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class DatabaseUtility {
private static DataSource dataSource;
static Connection conn;
public static void main(String ars[]) {
try {
conn = dataSource.getConnection();
System.out.println("connection established");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Your example code is a standalone Java program, although you also tagged the question with websphere-liberty. There are different ways of obtaining a data source from a standalone Java program vs when running in an application server (the latter).
Here is how to achieve it in Liberty.
Edit the server configuration (server.xml) file to enable one of the jdbc features,
<featureManager>
<feature>jdbc-4.2</feature>
<feature>jndi-1.0</feature> <!-- for JNDI lookup of the data source -->
<feature>servlet-4.0</feature> <!-- or other features that you want to use -->
</featureManager>
<dataSource id="myDataSource" jndiName="jdbc/myOracleDataSource">
<jdbcDriver libraryRef="OracleLib"/>
<properties.oracle URL="jdbc:oracle:thin:#//localhost:1521/SAMPLEDB" user="user1" password="password1"/>
</dataSource>
<library id="OracleLib">
<file name="C:/Oracle/lib/ojdbc8.jar"/>
</library>
Refer to example configuration on this knowledge center page for more information on data source configuration.
From a web or ejb component (servlet is used here), use resource injection as follows (this does not require the jndi-1.0 feature),
#WebServlet("/*")
public class ExampleServlet extends javax.servlet.http.HttpServlet {
#Resource(lookup = "jdbc/myOracleDataSource")
private DataSource dataSource;
public void init() throws ServletException {
// Here is another way of accessing the data source - via JNDI lookup.
// This requires the jndi-1.0 feature
DataSource anotherDataSource = InitialContext.doLookup("jdbc/myOracleDataSource");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
conn = dataSource.getConnection();
System.out.println("connection established");
response.getWriter().println("connection established");
} catch (Exception e) {
e.printStackTrace();
response.getWriter().println("failed to establish connection: " + e);
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Hello in my project to connect to the DB I was using contex.xml file (where I had all DB data) and #Resource(name = "xyz") annotation to and use it to create dataSource in my Servlet:
#WebServlet(name = "BookControllerServlet", urlPatterns = {"/BookControllerServlet"})
public class BookControllerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private BookDbUtil bookDbUtil;
#Resource(name = "sql2226123")
private DataSource dataSource;
// init method will be called by the app server when this servlet is loaded or initialized
#Override // we inherit it from GenericServlet
public void init() throws ServletException {
super.init(); //To change body of generated methods, choose Tools | Templates.
// create our book db util ... and pass in the connection pool / datasource
try {
bookDbUtil = new BookDbUtil(dataSource); // bookDbUtil is a data member that we've defined
} // dataSource is resource injection item our connection pool and we're passing it right here
catch (Exception exc) {
throw new ServletException(exc);
}
}
However, from day to day it suddenly stopped working. I mean #Resource(name = "sql2226123") does not provide any data. dataSource == null, myConn == null; What happened? context.xml is 100% good was not changed by this time. I had some jdk update recently if I remember correctly. Maybe it has something to do with it? My current java version is: 1.8.0_81-b13. Any ideas? Did anyone hear something about it?
Here is my context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<Context path="jadbc/ParkingSystem">
<Resource name="sql2226123"
auth="Container" type="javax.sql.DataSource"
maxActive="20" maxIdle="5" maxWait="10000"
username="sql2226123" password="xxxxxxxx"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://sql2.freemysqlhosting.net:3306/sql2226123"/>
</Context>
I also manage to get following error:
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 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;
}
}
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)