Use of pooling for my web App in servlet? - java

I'm using google app engine JAVA 8 and servlet 3.1 and would like to use HikariCP for pooling.
I'll write my logic in pseudo-code for better understanding.
At this point when user connects to a servlet it creates a new connection to database every time.
so my servlet looks a bit like this
doGet(){
DatabaseObject db = new DatabaseObject()
Connection conn = db.getConnection()
db.createTable(conn)
db.readData(conn)
...
conn.close()
}
Now I've seen many pooling examples like this one
but first I'm not sure this is what I'm trying to achieve also I don't really understand the whole process
Any examples, explanations are welcome as I've tried searching the net and couldn't find some for servlets. So maybe I'm thinking the wrong direction

That example looks like it stores the pool in the app (servlet) context.
I've done it differently. Usually I create a class, call it MyDb. Then I add various methods to it to access data. Within it there is a getConnection() method.
Internally, MyDb has its own connection pool. getConnection() simply returns a connection from the pool. The pool is initialized when the first MyDb is created.
Something like this (this is for app engine so no port is specified):
private static DataSource pool = null;
public MyDb( String dbhost, String dbdsn, String dbuid, String dbpwd )
{
try
{
if( MyDb.pool == null )
{
String dbconn = null;
String dbclassname = null;
HikariConfig config = new HikariConfig();
dbconn = "jdbc:google:mysql://" + dbhost + "/" + dbdsn;
dbclassname = "com.mysql.jdbc.GoogleDriver";
config.setJdbcUrl( dbconn );
config.setUsername( dbuid );
config.setPassword( dbpwd );
MyDb.pool = new HikariDataSource( config );
}
catch( Exception e )
{
logger.error( e.getMessage() );
}
}
protected Connection getConnection() throws Exception
{
return pool.getConnection();
}
}

Related

If I pass a JDBC Connection object's value to another Connection object, is only one connection open? (MySQL DB used) [duplicate]

This question already has answers here:
Difference between creating an instance variable and creating a new object in Java?
(6 answers)
Closed 6 years ago.
My method returns the value of a Connection object.
Public class DatabaseConnection
{
public Connection establishConnection(C)
{
try
{
this.readLogin(); // prompt user to enter String values for user, pass, host
this.createDatabaseIfNeeded(); // make chessleaguedb if not found
conn = DriverManager.getConnection
("jdbc:mysql://"+host+":3306/chessleaguedb", user, pass);
System.out.println("Successfully connected to chessleaguedb");
}
catch (Exception e)
{
// logic
}
return conn; // want the logic to handle opening a connection in this class and method, then pass it to a Connection object in my 'menu' class
}
}
This method is called in another class and passes the return value to a new Connection object that is used from now on.
public class DBAMenu
{
DatabaseConnection startConnection = new DatabaseConnection; // new instance of class that contains the aforementioned method establishConnection()
Connection conn = null;
conn = startConnection.establishConnection();
}
Is there only one database connection being opened here, or two, because I'm returning the value and passing it to a new Connection object?
I've tried using the NetBeans debugger, and the Connection value remains the same after this process, but admittedly I'm not 100% on the meaning of the value column in Netbeans debugger.
(Not using Java EE so can't use pooling, and can't use open source software to handle pooling as work must be my own for year 2 undergrad project)
If I pass a JDBC Connection object's value to another Connection object, is only one connection open?
You don't have 'another Connection object'. You have another reference of type Connection. Both references refer to the same object.
You have used only one connection as you have invoked conn = startConnection.establishConnection(); only once.
You need to implement close the connection, otherwise it will create connection leaks.
You can use like below:
try(Connection conn =startConnection.establishConnection()) {
//actual logic to perform db operations
} catch(SQLException sqlexe) {
//log exceptions
}
P.S.: It is not a best practice to handle connections explicitly/manually like this, rather try to implement Connection Pooling.

Connect to MySQL with Java - JDBC without showing credentials in Java source code

I am trying to learn how you would tackle the task of creating a Java console application, connect to a (in this case) MySQL DB and send or retrieve data, without showing your username and password in the source code of the Java application. I currently have no trouble
creating a connection showing credentials.
// JDBC driver name and database URL
private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
private static final String DB_URL = "jdbc:mysql://192.168.1.159:3306/javahelper";
// Database credentials
private static final String USER = "xxxx";
private static final String PASS = "RandomString";
/**
* #return
*/
public Connection openConnection() {
Connection connection = null;
try {
Class.forName(JDBC_DRIVER);
// opening connection
connection = (Connection) DriverManager.getConnection(DB_URL,USER,PASS);
} catch (ClassNotFoundException e) {
System.out.println("This is from openConnection method");
e.printStackTrace();
} catch (SQLException f) {
System.out.println("This is from openConnection method");
f.printStackTrace();
}
return connection;
}
From what information I can gather you always need to show your credentials somewhere in the application. But how do you than achieve "safe" connection between a application and a DB, so others can't misuse your credentials for malicious reasons?
one way of doing it is using a properties file having your credentials or having your data in a xml file.
create a properties file like the one below
// database.properties
DB_URL=jdbc:mysql://localhost:3306/UserDB
DB_USERNAME=user_name
DB_PASSWORD=password
Use this information in your code to get the username and passwords.
Properties properties= new Properties();
FileInputStream input = null;
try{
input = new FileInputStream("database.properties");
props.load(input );
con = DriverManager.getConnection(props.getProperty("DB_URL"),props.getProperty("DB_USERNAME"),props.getProperty("DB_PASSWORD"));
}
you can use encrypt the username and password.The best opensource encryptor(My personal view) is jbcrypt
// Hash a password for the first time
String hashed = BCrypt.hashpw(password, BCrypt.gensalt());
// gensalt's log_rounds parameter determines the complexity
// the work factor is 2**log_rounds, and the default is 10
String hashed = BCrypt.hashpw(password, BCrypt.gensalt(12));
// Check that an unencrypted password matches one that has
// previously been hashed
if (BCrypt.checkpw(candidate, hashed))
System.out.println("It matches");
else
System.out.println("It does not match");
Sharing what i find
Creating and using the propertise file
I created a database.properties file(normal text file) and placed it in the src folder of the Java project.
JDBC_DRIVER=com.mysql.jdbc.Driver
USER=YourUser
PASS=YourPassword
DB_URL=jdbc:mysql://IP:PORT/DB
Afterwards i edited my openConnection() method to use the properties file for loading the credientials of the connection.
public Connection openConnection() {
Properties properties = new Properties();
Connection connection = null;
String path = System.getProperty("user.dir");
path += "/src/database.properties";
try(FileInputStream fin = new FileInputStream(path);) {
properties.load(fin);
try {
Class.forName(properties.getProperty("JDBC_DRIVER"));
// opening connection
connection = (Connection) DriverManager.getConnection(properties.getProperty("DB_URL"),properties.getProperty("USER"),properties.getProperty("PASS"));
} catch (ClassNotFoundException e) {
System.out.println("This is from openConnection method");
e.printStackTrace();
} catch (SQLException f) {
System.out.println("This is from openConnection method");
f.printStackTrace();
}
} catch (IOException io) {
System.out.println("This is from openConnection method");
io.printStackTrace();
}
return connection;
}
Sending username and password, Java application -> MySQL
From what i can read on the web, it dosent matter much if you encrypt or hash the password before you send it towards the sequel service from your Java application. An example i found is that the sequel service dosent have a "receive hash method and authenticate". And even if it did the hash would need to be in the program somewhere. And when the program has access to it, others also have access to it if they really want it. Also if the hash is whats needed to authenticate than your back to where you can just as well use the clear text password.
The discussion than ends on "what is the best approach". Some suggest a keyserver / auth system in between the application and sequel service, using a datastore setup on the server side, using the OS "wallet" (example Windows registry) or creating a database user with minimum permissions to just get the job done / or a read only DB "read_only=1 in my.cnf".
I tried the 3'rd option and created a "DBaccess" user, with only the select permission to retrieve data, no administrative rights and random generated password by MySQL.

Trying to connect to my sql database getting exception saying "no suitable driver found"

I'm using the tutorial at http://www.vogella.com/tutorials/MySQLJava/article.html
to try tp connect to my sql server on my server
When it executes the line:
Connection connect = DriverManager
.getConnection("jdbc:mysql:http://www.findmeontheweb.biz"
+ "user=findmeon_bitcoin&password=PASSWORD");
an exception gets thrown saying "No sutabled driver found for jdbc:mysql:http://www.findmeontheweb.biz
This is what I did
1. Downloaded the "mysql-connecter-java-5.1.33.bin.jar into my lib folder
2. added the jar to my project from preferences.
project code:
public class cStart {
private Connection connect = null;
private Statement statement = null;
private PreparedStatement preparedStatement = null;
private ResultSet resultSet = null;
public static void main (String[] args) {
int g=0;
try {
// this will load the MySQL driver, each DB has its own driver
Class.forName("com.mysql.jdbc.Driver");
// setup the connection with the DB.
// EXCEPTION GOES OF HEAR
Connection connect = DriverManager
.getConnection("jdbc:mysql:http://www.findmeontheweb.biz"
+ "user=findmeon_bitcoin&password=PASSWORD");
} catch (Exception e) {
System.out.println("Exception...." );
}
}
}
The URL format should be look like this
jdbc:mysql://hostname/ databaseName
I think this is a much cleaner way to do it:
String URL = "jdbc:URL_TO_YOUR_DATBASE";
String USER = "username";
String PASS = "password"
Connection conn = DriverManager.getConnection(URL, USER, PASS);
As seen here: http://www.tutorialspoint.com/jdbc/jdbc-db-connections.htm
I say give that link a try with your driver. You also should make sure you have the actual jar for MySQL. It really might be invalid.
I would try the one here: http://www.java2s.com/Code/Jar/c/Downloadcommysqljdbc515jar.htm
And then add that to your project.
The URL to the database might be wrong.
If yes you should specify a correct one with including database name.
Else verify if the jdbc driver jar is added in the build-path, if yes try to put it in the lib folder of your webapp.

How to connect to a Cloud Foundry MySQL database connection in Java?

create mysql as service on Cloud Foundry and tunnel to mysql database
this provides me connection string to mysql database i pass that information to my app.
it works from my machine but when i deployed that app on Cloud Foundry server then it gives an error in connection
this is my connection code, tell me what needs to change to be deployed on Cloud Foundry
public class DB {
private static Connection connection = null;
public static Connection getConnection() {
String url = "jdbc:mysql://127.0.0.1:10100/db8dad2d02e114ef6bc9d24e68367e33e";
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(url,"uC0ag3NRJCT8c","p1nyZ38zadwfa");
System.out.println("Connect success fully");
return connection;
} catch (Exception e) {
System.out.println("Error");
System.out.println(e);
e.printStackTrace();
}
return null;
}
}
jayesh's answer is technically correct, but basically, the best way to deal with retrieving those information when inside a java app (assuming non-spring) is to use the cloudfoundry-runtime library: https://github.com/cloudfoundry/vcap-java/tree/master/cloudfoundry-runtime The README has examples of usage.
For completness, if using Spring, then things are even easier and chances are you don't even need to do anything special
Problem is here:
jdbc:mysql://127.0.0.1:10100
In this you're connecting to 127.0.0.1, it is a localhost, try giving the actual IP of your cloud server. Then it should work fine.
try {
String vcap_services = System.getenv("VCAP_SERVICES");
String hostname = "";
String dbname = "";
String user = "";
String password = "";
String port = "";
//for cloud config
if (vcap_services != null && vcap_services.length() > 0) {
JsonRootNode root = new JdomParser().parse(vcap_services);
JsonNode mysqlNode = root.getNode("mysql-5.1");
JsonNode credentials = mysqlNode.getNode(0).getNode(
"credentials");
dbname = credentials.getStringValue("name");
hostname = credentials.getStringValue("hostname");
user = credentials.getStringValue("user");
password = credentials.getStringValue("password");
port = credentials.getNumberValue("port");
String dbUrl = "jdbc:mysql://" + hostname + ":" + port + "/"
+ dbname;
System.out.println(dbUrl);
System.out.println(user + "password " + password);
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(dbUrl, user, password);
return connection;
} else {
//for local configuration
Class.forName("com.mysql.jdbc.Driver");
String url = jdbc:mysql://127.0.0.1:10100/db8dad2d02e114ef6bc9d24e68367e33e
connection = DriverManager.getConnection(url, "user name",
"password");
return connection;
}
} catch (Exception e) {
e.printStackTrace();
}
You're using information from vmc tunnel to try to connect. This is not going to work on the Cloud. You need to do what jayesh shows, and read the connection credentials from the Cloud Foundry environment instead. Eric's answer is even more complete :-)
I have the same problem. You must notice that "10100" is a port fortwarding to the mysql remote service.
you could use this just locally.Deploying your program locally with your database connection pointing to the forwarding port (101100).
But this won't work when you push your war to the Cloud Foundry Instance-
One solution is to use Spring based cloud beans. In my case i don't wan't to use this approach so i'm trying another solution...
I don't know if with the credentials (user, password, tc) created for the remote connection you could stablish a connection once you pushed your war to Cloud Foundry changing the forwarding port and using the default mysql port (3360)
In my case i don't want to use Spring Cloud Beans because the production application won't be deployed into a cloud storage.

Deleting a row from the mysql database in a web application

Please suggest me the piece of code for deleting a row from a mysql database that contains three columns problemid, problem and solution.
I want to delete it from a browser i.e. it is a web application.
You may consider using JDBC (Java Database Connectivity) API for your problem. I recommend you to take a close look at the following simple tutorials about developing Java Web Applications Using a MySQL Database.
https://blogs.oracle.com/JavaFundamentals/entry/creating_a_simple_web_application
http://www.javaguicodexample.com/javawebmysqljspjstljsf5.html
Here is a sample Servlet.
But please remember this is just to show you how to do it, you SHOULD NOT use this in a productive system!This is more for demonstration, look at it how and learn how to do it.
This servlet should run fine, but there are some things you have to do!
Anyway you should read these documents, if you haven't already done it
http://docs.oracle.com/javaee/5/tutorial/doc/bnadp.html
http://docs.oracle.com/javase/tutorial/jdbc/basics/index.html
Things which i havent taken into account, while i wrote this:
Request Parameters
If one of the request parameters cannot be found, it will throw an Exception. You need a better way of handling with this situation.
Connection Pooling
This example will open a connection to the database on EVERY request. Opening a connection costs time. Therefore everyone use a connection pool. This library/server opens a specified amount of connections to the database. Everytime you need to access the database you fetch it from this pool and if you're finished you return it to the pool.
Security
Someone who knows the address of this servlet, could easily use it to delete any row in your table. This is your job to secure it.
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
/**
* DON'T USE IN PRODUCTION, JUST FOR LEARNING PURPOSES
**/
public class MySqlServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long problemId;
long problem;
long solution;
Object problemIdAsObject = request.getParameter("problemId");
Object problemAsObject = request.getParameter("problem");
Object solutionAsObject = request.getParameter("solution");
if ( problemIdAsObject == null ){
throw new ServletException("problemId has not been specified!");
}
if ( problemAsObject == null ){
throw new ServletException("problem has not been specified!");
}
if ( solutionAsObject == null ){
throw new ServletException("solution has not been specified!");
}
problemId = Long.valueOf( (String)problemIdAsObject );
problem = Long.valueOf( (String)problemAsObject );
solution = Long.valueOf( (String)solutionAsObject );
PreparedStatement statement = null;
Connection connectionToDatabase = null;
try{
connectionToDatabase = getConnection();
String sql = "DELETE FROM table WHERE problemid = ? and "+
"problem = ? and solution = ?";
statement = connectionToDatabase.prepareStatement(sql);
statement.setLong(1,problemId);
statement.setLong(2,problem);
statement.setLong(3,solution);
statement.execute();
}catch( SQLException sqle ){
throw new ServletException(sqle);
}catch( ClassNotFoundException cnfe ){
throw new ServletException(cnfe);
}finally{
try{
statement.close();
connectionToDatabase.close();
}catch( SQLException sqle ){
throw new ServletException(sqle);
}
}
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<BODY>");
out.println("OK");
out.println("</BODY></HTML>");
}
private Connection getConnection()
throws ClassNotFoundException,SQLException{
String userName = "user";
String password = "password";
String databaseName = "database";
String serverAddress = "localhost";
String connectionString = "jdbc:mysql://"+serverAddress+"/"+databaseName+
"?user="+userName+"&password="+password;
//If this line is not working, use this instead:
//Class.forName("com.mysql.jdbc.Driver").newInstance();
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(connectionString);
return connection;
}
}
It's so simple buddy, first of all you have to make a link to any servlet from jsp. And with that link you have to pass the deleted record id as parameter & write the code inside servlet for deleting the given row from database. And then return that same page where the previous link you have clicked.

Categories

Resources