Can't access MySQL Database After deploying to the Cloud - CommunicationsException - java

I connect to my Google Cloud SQL via my App Engine Java Rest API Project to retrieve and store data on my cloud. I can successfully communicate with the server via Localhost but after I publish, I get this error:
Trying to Run Query:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
Communications link failure
The last packet sent successfully to the server was 0 milliseconds
ago. The driver has not received any packets from the server.
While there's so many solutions out there, I'm sad to say none of them worked.
Here's my connection string:
String url = null;
try {
if (SystemProperty.environment.value() == SystemProperty.Environment.Value.Production) {
Class.forName("com.mysql.jdbc.GoogleDriver");
url = "jdbc:google:mysql://APP_ENGINE_ID:SQL_INSTANCE_NAME/DB_NAME?user=root";
} else {
Class.forName("com.mysql.jdbc.Driver");
url = "jdbc:mysql://MY_IPV4_ADDRESS:3306/DB_NAME?user=root";
}
} catch (Exception e) {
e.printStackTrace();
}
I get this error via my Rest API after I publish it only. Basically, works via Localhost but not remotely on the cloud.
I debugged and pin pointed the place where it crashes. It happens after I try to establish a connection with the server and execute a query:
try {
//THIS is where it crashes
conn = DriverManager.getConnection(url);
try {
String query = "SELECT * FROM UserTable";
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(query);
while (rs.next())
{
//Code
}
st.close();
} finally {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
Has anyone faced this issue before?

Like Herman, Igor and Vadim pointed out, it was a simply error in my PROJECT_ID:INSTANCE_ID in this line:
Incorrect Code:
if (SystemProperty.environment.value() == SystemProperty.Environment.Value.Production) {
Class.forName("com.mysql.jdbc.GoogleDriver");
url = "jdbc:google:mysql://APP_ENGINE_ID:SQL_INSTANCE_NAME/DB_NAME?user=root";
}
I've been using my App engine ID instead of the Project ID, which I should have been using.
Corrected Code:
if (SystemProperty.environment.value() == SystemProperty.Environment.Value.Production) {
Class.forName("com.mysql.jdbc.GoogleDriver");
url = "jdbc:google:mysql://PROJECT_ID:SQL_INSTANCE_NAME/DB_NAME?user=root";
}

as You can see i have called using asyncTask in Android (same as Thread in java )
public class Connect extends AsyncTask<Context, Integer, Long>
{
protected Long doInBackground(Context... contexts) {
Connection connection;
String query = "Some query";
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://<your cloud IP address>/<database schema you want to connect to>", "<user>", "<password>");
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query);
hope you got it now :)

Related

Create connection to SQL database using JDBC Driver- SQLException [duplicate]

I am trying to connect to my database by JDBC on localhost. Connecting via windows authentication is no problem, but I want to connect via SQL authentication. Therefore, I created a login and a user corresponding to this login in my database. I can normally log in SSMS:
My connection string for JDBC:
jdbc:sqlserver://localhost:1433;databaseName=TestBazyDanych;user=doszke;password=doszke123
Thrown exception:
com.microsoft.sqlserver.jdbc.SQLServerException: Login failed for user 'doszke'. ClientConnectionId:b7005fe3-904d-40c5-a89e-af0cb61250d6
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:254)
at com.microsoft.sqlserver.jdbc.TDSTokenHandler.onEOF(tdsparser.java:258)
at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:104)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.sendLogon(SQLServerConnection.java:4772)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.logon(SQLServerConnection.java:3581)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.access$000(SQLServerConnection.java:81)
at com.microsoft.sqlserver.jdbc.SQLServerConnection$LogonCommand.doExecute(SQLServerConnection.java:3541)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7240)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2869)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:2395)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:2042)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectInternal(SQLServerConnection.java:1889)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:1120)
at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:700)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:251)
at main.Main.main(Main.java:38)
The username and password are the same, as those used for loging to SSMS.
Here my class code:
package main;
import java.sql.*;
public class Main {
private static ResultSet selectStan(Connection connection) throws SQLException {
String sql_stmt = "SELECT * FROM STAN;";
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery(sql_stmt);
System.out.println("Select executed");
return result;
}
public static void main(String[] args) {
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String userName = "doszke";
String password = "doszke123";
String url = "jdbc:sqlserver://localhost:1433;databaseName=TestBazyDanych;user=doszke;password=doszke123";
try (Connection con = DriverManager.getConnection(url)) {
if(con != null){
System.out.println("connected");
} else {
System.out.println("unable to connect");
}
}
catch (SQLException e) {
e.printStackTrace();
}
}
}
As Mark Rotteveel pointed out, I was trying to connect to a LocalDB instance with JDBC, which seemed undoable. (ref: here)
However, I installed jTDS and added to my classpath, changed my connection string to
jdbc:jtds:sqlserver://./TestBazyDanych;instance=LOCALDB#EB7165FD;namedPipe=true
create a connection by the use of this connection string, username and password and it worked. The instance pipe number was taken from cmd line via
sqllocaldb i MSSQLLocalDB
There are few things need to check:
Did you create doszke user under the database and SSMS?
Are you able to login with doszke/doszke123 credentials in SSMS?
Please check 1433 port are open or not in your inbound and outbound firewall.
Trying to telnet on localhost 1433. If it's getting failed change below setting:
Go to Configuration tools -> SQL Server Configuration Manager Select SQL Server Network Configuration -> Select protocol in the right side window enable tcp/ip and restart the services in services.

Java JDBC Communications link failure after deploying online

I have created my first API using java httpServlet on netbeans. After days working I could finally connect it to this mySQL googleCloud database and get results locally. But once this API is published on google cloud using appengine, below error was thrown:
Error sqlException:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
Communications link failure The last packet sent successfully to the server was 0
milliseconds ago. The driver has not received any packets from the server.
But the mySQL database is allowing access for all IPs, so what could be the problem? Below is my code:
public class HelloServlet extends HttpServlet {
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
PrintWriter out = resp.getWriter();
//out.println("Dear vistor, you are accessing my first project deployed on cloud. Thank you");
try {
Class.forName("com.mysql.jdbc.Driver");
String url = String.format("jdbc:mysql://IP:3306/DatabaseName?useSSL=false&useUnicode=true&characterEncoding=UTF-8");
Connection connection = DriverManager.getConnection(url, "userName", "Password");
try (Statement statement = connection.createStatement()) {
ResultSet resultSet = statement.executeQuery("select test from tableTest;");
while (resultSet.next()) {
out.println(resultSet.getString(1));
}
}
} catch (ClassNotFoundException ex) {
out.println("Error ClassNotFoundException:" + ex.toString());
} catch (SQLException ex) {
out.println("Error sqlException:" + ex.toString());
}
catch(Exception ex){
out.println("Exception:" + ex.toString());
}
}
}
Update:
Based on this link, I have discovered that when publishing online I should not use a password. So I have updated my code to use jdbc google drive in this way:
Class.forName("com.mysql.jdbc.GoogleDriver");
String url = String.format("jdbc:google:mysql://appId:instanceId/dbName?user=root");
Connection connection = DriverManager.getConnection(url);
But when I published online , same error was thrown...
Update2:
Could it be bcause my appId contains "-" like "test-123"? But actually I am sending my url in this form:
url = "jdbc:google:mysql://test-123:myInstance/myDatabase?user=root&useUnicode=true&characterEncoding=UTF-8";

How can the java SQL connector be used to connect to a database on a different computer

I have a simple database on my computer for testing purposed, and I'm trying to retrieve some information from the database, from my laptop. So I want my laptop to make a request to see the information inside my computers MySQL database. Below shows the java code I'm trying to run on my laptop to collect the first entry in the students table, which is located on my computer.
I have MySQL workbench installed on both my laptop and computer, is it necessary to be on both machines if the computer will store the data and the laptop only extracts data.
What I've learnt so far from researching is that the public ip should be used in the url instead of the ip for the computer, so I added that in but I received a CommunicationsException along with "Connection timed out" in the stack trace. I've read through this answer and this answer to a similar problem, but I'm having difficulty understanding both solutions, could someone refer me to a beginners guide to remotely accessing data from a database using MySQL.
public class TestRemote{
//JDBC variables
Connection connection;
Statement statement;
ResultSet resultSet;
//String variables
String url;
String user;
String password;
public static void main(String[] args) {
TestRemote sql = new TestRemote();
ArrayList<String> firstnames = sql.getColumn("students", "firstname", "studentid=4");
System.out.println(firstnames.get(0));
}
// Constructor
public TestRemote()
{
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.out.println("couldnt find class");
}
url = "jdbc:mysql://81.159.3.167:3306/test"; //?autoReconnect=true&useSSL=false";
user = "user";
password = "pass123";
connection = null;
statement = null;
resultSet = null;
}
private void closeConnection(){
try{
if(connection != null)
connection.close();
if(statement != null)
statement.close();
if(resultSet != null)
resultSet.close();
connection=null; resultSet=null; statement=null;
}catch(Exception e){
e.printStackTrace();
}
}
public ArrayList<String> getColumn(String table, String column, String where) {
ArrayList<String> resultsArray = new ArrayList<String>();
try {
connection = DriverManager.getConnection(url, user, password);
statement = connection.createStatement();
if(!where.equals(""))
resultSet = statement.executeQuery("SELECT "+column+" FROM "+table + " WHERE "+where);
else
resultSet = statement.executeQuery("SELECT "+column+" FROM "+table);
while(resultSet.next()) {
String val = resultSet.getString(1);
if(val==null)
resultsArray.add("");
else
resultsArray.add(val);
}
//resultsArray = (ArrayList<String>) resultSet.getArray(column);
} catch (SQLException ex) {
Logger lgr = Logger.getLogger(Model.class.getName());
lgr.log(Level.SEVERE, ex.getMessage(), ex);
}
closeConnection();
return resultsArray;
}
}
Your Java code is probably fine. But the question is, is on the other machine a MySQL server running and listening on port 3306 on the public IP? By default it should only listen on localhost, so you need to change your MySQL installation so that it listens to the public IP. Also make sure that no Firewall is blocking the access. Try connecting with the Workbench on the Laptop to reach the MySQL server on the other box. If you got this running, try your Java code again.
I have MySQL workbench installed on both my laptop and computer, is it
necessary to be on both machines if the computer will store the data
and the laptop only extracts data.
No what you call the "Computer" is your server here. it doesn't need mysql workbench. it only needs mysql server
the public ip should be used in the url instead of the ip for the
computer
A database should almost never be exposed on the public IP address. If you are having both computers on the LAN, the private network IP is what the server should listen on and that's what you should use on the connection string.
CommunicationsException along with "Connection timed out" in the stack
trace
Because the server is not running, not listening on that ip:port or firewalled to drop packets.

Java Database mySQL access denied

So I am trying to connect to my database and display an item from the table.
The error I am getting is: SQL Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Access denied for user 'Bob'#'%' to database 'TEST'
Is this connecting properly, and if so is the error that the credentials are wrong? And if they are wrong how is it connecting? Thank you
try
{
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://THISISTHEHOSTNAME";
String username = "Bob";
String password = "password";
Connection connection = DriverManager.getConnection(url, username, password);
Statement stmt = null;
ResultSet rs = null;
//SQL query command
String SQL = "SELECT * FROM TEST";
stmt = connection.createStatement();
rs = stmt.executeQuery(SQL);
while (rs.next())
{
System.out.println(rs.getString("ProductName") + " : " + rs.getString("UnitPrice"));
}
}
catch (SQLException e)
{
System.out.println("SQL Exception: "+ e.toString());
}
catch (ClassNotFoundException cE)
{
System.out.println("Class Not Found Exception: "+ cE.toString());
}
You need to grant the proper privileges to the user that is connecting to the mysql db.
The message you are getting is informing you that while your user was able to connect to the database server, it was not allowed to access the database TEST.
Running the following command in the mysql console would grant such access:
GRANT ALL ON TEST.* TO 'BOB'#'%'
This is extremely permissive and you should keep in mind that db users should have the minimal amount of privileges possible and be restricted to the smallest range of hosts.
I used ShowIP Firefox add on and used the IP instead and didn't get any errors but I'm wondering if should return access granted and I'm unable to find an answer at the moment.
Here's a few things to do:
Check to see if your username and password are correct.
Did you add the username to the correct database? (This needs to be done in CPanel SQL)
Did you allow your database to get connection access from your IP address? (This also needs to be done in CPanel SQL)
create a new user in mysql check all global privileges > go to service in netbeans > database > mysql server at localhost > right click connect and fill username password
this work for me
Please try the code below:
import java.sql.*;
public class InsertPrepared {
public static void main(String[] args)
{
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306//test","sanjib","");
PreparedStatement stmt=con.prepareStatement("insert into employee values(???)");
stmt.setInt(1,101);
stmt.setString(2,"Sampa");
int i=stmt.executeUpdate();
System.out.println(i+"Records is inserted");
con.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
}

Why can't I get a remote data source within an applet?

I trying to do a JNDI lookup on a data source that lives in Weblogic 10.3.5.
I have the following code:
try {
//jbInit();
env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
env.put(javax.naming.Context.PROVIDER_URL,"t3://localhost:7001");
try {
Context ctx = new InitialContext(env);
javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup("jdbc/sandboxDS");
conn = ds.getConnection();
} catch(Exception e){
e.printStackTrace();
}
if(conn != null){
System.out.println("Got connection...");
String colDescQuery =
"select column1 from my_table where table_name = 'your_table' order by col_order_no";
Statement colDescStmt = conn.createStatement();
ResultSet colDescRS = colDescStmt.executeQuery(colDescQuery);
while (colDescRS.next()) {
System.out.println(colDescRS.getString(1));
}
} else {
System.out.println("No connection...");
}
} catch (Exception e) {
e.printStackTrace();
}
When I run this code as a stand alone Java program it works perfectly. The connection is found and the query returns the expected results.
When I use the same code in an applet and run it from the JDeveloper applet viewer it hangs where the InitialContext is instantiated. No exceptions are thrown, it simply hangs never to return.
Any ideas as to what is going on here? I have weblogic.jar and wlthint3client.jar in my classpath for both runs.
Thanks...
Applets have sandbox restrictions, so they cannot connect to the server other than where they were downloaded from.
Make sure your applet is also deployed to the same WebLogic Server that your JNDI data source is on.

Categories