Java: Trouble connecting to MySQL - java

I'm writing a desktop java app on that I want to connect to a MySQL database on a server. Here is the code to do that:
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
private static Connection getDBConnection() throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException {
String username = "myUserName";
String password = "myPassWord";
String url = "jdbc:mysql://www.domainName.com:3306/databaseName";
Class.forName("com.mysql.jdbc.Driver");
System.out.println("Connecting to database...");
//hangs here
Connection conn = DriverManager.getConnection(url, username, password);
return conn;
}
When I run this, it hangs on the DriverManager.getConnection() call. Why does this happen? Is my URL malformed?
(I'm not getting any error messages, but the program doesn't respond as if in an infinite loop. I haven't waited longer than 90 seconds to see if the connection will ever be established.)
Also, what is the purpose of the Class.forName() call? How does it work?
I am almost entirely certain that the username and password are correct. (I just used userName and passWord as placeholders above.)
UPDATE: I fixed the port number, and now I get this error:
Cannot connect to database: java.sql.SQLException: Access denied
for user 'userName'#'r236059121.resnet.mySchool.edu' (using
password: YES)
Does this mean I need to configure settings on the database? Or does it mean that I've got the credentials wrong? (They work for PHP scripts deployed on the server that contains the database.)
SOLUTION: Added the host above to the Access Host list on cPanel.

Seems to me like your database is not reachable and you will probably get an error when the call runs into a timeout. Are you sure the hostname and port are right and reachable from your machine?
You don't need the newInstance() at the end of Class.forName(). Class.forName() triggers the classloader to load that class, which in turn triggers some internal registration code in the driver which makes the driver available.

I think the line should just be
Class.forName("com.mysql.jdbc.Driver");
(close the .newInstance() bit)
That causes the driver to register itself with the driver manager and allows the driver manager to pick a driver for the database url.
I think the hang is caused by a DNS problem, or some other reason why your db cannot be reached. By default, the MySQL JDBC driver does not time out for a connection. See http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-configuration-properties.html and look for connectTimeout.
In your code, you have
String url = "jdbc:mysql://www.domainName.com:portNumber/databaseName";
I take it that you used a real port there? By default, it should be 3306. You can test with the test database which is present in virtually all mysql instances:
String url = "jdbc:mysql://www.domainName.com:3306/test";
You also wrote:
String username = "myUserName";
String password = "myPassWord";
Obviously you should use real credentials here too. Ask your dba what they are. If you're the DBA then...well you should probably read up on MySQl administration :) Seriously when you installed MySQL you were probably promted for a password for the root user. Use those (in the obvious way)
In real code you should probably not hang when the db is not there. So I advise adding a connectTimeout option like so:
String url = "jdbc:mysql://www.domainName.com:3306/test?connectTimeout=3000";
(connectTimeout is in milliseconds, so this would time out after 3 seconds)

Rosarch - You are not able to connect to your DB since its unreachable.
It'll timeout after a while.
Try telnetting -
telnet <IP-OF-domainName.com> <PortNumber>
You'll mostly see that it shows timeout.
Solutions -
1.) If you are behind a firewall, you need to punch a hole to allow access
2.) If you are behind a proxy, need to configure it to allow access

Related

Encrypting database login information mySQL connector

I'm new to programming and I am a little lost. I'm building a desktop app that upon being launched, prompts the user to log in and the app then connects to my sites mySQL database and verifies it and if the user is found, then a second JFrame appears and the user can now use the program.
I hadn't thought of that, but now I'm faced with the problem of someone decompiling the app and getting access to the mySQL connection details.
Here is a trimmed version of the connection code for reference.
import java.sql.Connection;
import java.sql.DriverManager;
public class databaseConnection {
public static void main(String[] args) throws Exception {
getConnection();
}
public static Connection getConnection() throws Exception {
try {
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/dbase";
String username = "root";
String password = "root";
Class.forName(driver);
Connection conn = DriverManager.getConnection(url,
username, password);
System.out.println("Connected.");
return conn;
} catch (Exception e) {
System.out.println(e);
}
return null;
}
}
Is there a way to hide or encrypt the url, username and password? I understand nothing is absoluetly secure and this would just make it a tad harder for someone with malicious intent, but strasight up leaving the information for anyone to see seems a little foolish.
thanks
There's no good way to solve this issue, which is why you don't see that many desktop programs connecting to a central database (anymore). Any credentials contained inside your programs are visible. Sure, you can use any amount of time you want to invent "security schemes", but it won't change the fact that it's just insecure.
You have basically three ways to avoid that issues. Make your application a webapp so the users can't access the code, make your users set up their own databases with their own credentials (this obviously won't help if you want all users to be able to exchange information between each other) or thirdly, write a backend layer so the desktop clients don't connect to the database directly. They would then send commands to the backend to perform database operations, and you can control the backend credentials to allow connections to whom you want.

PGJDBC: could not receive data from client:

Dear StackOverFlowers,
I was trying event-driven LISTENER/NOTIFY on Postgres 9.6 (Windows 10).
I followed PGJDBC example given by Steve Taylor at https://www.openmakesoftware.com/postgresql-listen-notify-events-example/.
I started by downloading pgjdbc-ng-0.7-complete.jar and have put that in my CLASSPATH replacing standard JDBC driver.
When I am trying to connect to Postgres database using pgjdbc driver, I am getting an error:
connection received: host=127.0.0.1 port=50325
connection authorized: user=postgres database=scott
could not receive data from client: An existing connection was forcibly closed by the remote host.
Here are my system variables:
DBHost: localhost
DBName: scott
DBPort: 5432
DBUserName: postgres
DBPassword: postgres
I am not getting past the first hurdle, rest looks like Mount Everest. Please help me. Should you be needing the code, I am following Steve's code ditto.
Further to Joseph Larson's answer, the database is always running. I have connected to Postgres database from PGADMIN and Java successfully. I think issue is with the connect string. From Java when I am using standard JDBC which is provided by Postgres I am using URL like jdbc:postgresql://localhost:5432/dbname but PGJDBC suggests a different connect string like JDBC:PGSQL://localhost:5432/dbname. I tried to connect with that string (forcibly), it did not work. There is no method in PGJDBC PGDataSource for providing URL directly. I had to go through:
dataSource.setHost(DBHost);
dataSource.setPort(5432);
dataSource.setDatabase(DBName);
dataSource.setUser(DBUserName);
dataSource.setPassword(DBPassword);
And what URL it is sending to Database I am not able to figure out. Please suggest me a connect string and this problem is solved.
thanks
Thanks very much for asking me to post error messages:
Exception in thread "main" java.lang.NullPointerException
at com.impossibl.postgres.system.BasicContext.loadLocale(BasicContext.java:294)
at com.impossibl.postgres.system.BasicContext.init(BasicContext.java:273)
at com.impossibl.postgres.jdbc.PGConnectionImpl.init(PGConnectionImpl.java:251)
at com.impossibl.postgres.jdbc.ConnectionUtil.createConnection(ConnectionUtil.java:182)
at com.impossibl.postgres.jdbc.AbstractDataSource.createConnection(AbstractDataSource.java:723)
at com.impossibl.postgres.jdbc.PGDataSource.getConnection(PGDataSource.java:66)
at com.impossibl.postgres.jdbc.PGDataSource.getConnection(PGDataSource.java:58)
at PGListenNotify.<init>(PGListenNotify.java:26)
at PGListenNotify.main(PGListenNotify.java:37)
Here is source code:
import java.sql.SQLException;
import java.sql.Statement;
import com.impossibl.postgres.api.jdbc.PGConnection;
import com.impossibl.postgres.jdbc.PGDataSource;
public class PGListenNotify
{
PGConnection connection;
public PGListenNotify()
{
String DBHost = System.getenv("DBHost");
String DBName = System.getenv("DBName");
String DBUserName = System.getenv("DBUserName");
String DBPassword = System.getenv("DBPassword");
try
{
PGDataSource dataSource = new PGDataSource();
dataSource.setHost(DBHost);
dataSource.setPort(5432);
dataSource.setDatabase(DBName);
dataSource.setUser(DBUserName);
dataSource.setPassword(DBPassword);
connection = (PGConnection) dataSource.getConnection();
Statement statement = connection.createStatement();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
PGListenNotify ln = new PGListenNotify();
}
}
This looks like the Windows locale bug in pgjbdc-ng. It has been addressed, try the latest version 0.8.1.
The latest releases have detailed documentation related to asynchronous notifications here.
If it still fails to execute on your Windows system, please create an issue here.
Did you actually start a database server? I didn't know PostgreSQL server could run on Windows, but I've never tried.
I would simplify your problem a little. I know nothing about psql on Windows, but on Mac, I would start the server and then use the psql command (it's part of PostgreSQL) to ensure the server was up and running.
If you're to connecting, then the problems can be:
-There is no server at all
-The server isn't running on the port you're attempting
-The server isn't listening for connections on host 127.0.0.1 but could be listening on the actual IP address of your machine
-I'm not sure about that particular error, but username, password, or database may not exist.
I'd use psql to figure out which of those possible reasons is the real problem. That isolates out your program as being part of the problem, and it becomes entirely one of managing your database server.

Hive JDBC connection problems

I am trying to connect to Hive2 server via JDBC with kerberos authentication. After numerous attempts to make it work, I can't get it to work with the Cloudera driver.
If someone can help me to solve the problem, I can greatly appreciate it.
I have this method:
private Connection establishConnection() {
final String driverPropertyClassName = "driver";
final String urlProperty = "url";
Properties hiveProperties = config.getMatchingProperties("hive.jdbc");
String driverClassName = (String) hiveProperties.remove(driverPropertyClassName);
String url = (String) hiveProperties.remove(urlProperty);
Configuration hadoopConfig = new Configuration();
hadoopConfig.set("hadoop.security.authentication", "Kerberos");
String p = config.getProperty("hadoop.core.site.path");
Path path = new Path(p);
hadoopConfig.addResource(path);
UserGroupInformation.setConfiguration(hadoopConfig);
Connection conn = null;
if (driverClassName != null) {
try {
UserGroupInformation.loginUserFromKeytab(config.getProperty("login.user"), config.getProperty("keytab.file"));
Driver driver = (Driver) Class.forName(driverClassName).newInstance();
DriverManager.registerDriver(driver);
conn = DriverManager.getConnection(url, hiveProperties);
} catch (Throwable e) {
LOG.error("Failed to establish Hive connection", e);
}
}
return conn;
}
URL for the server, that I am getting from the properties in the format described in Cloudera documentation
I am getting an exception:
2018-05-05 18:26:49 ERROR HiveReader:147 - Failed to establish Hive connection
java.sql.SQLException: [Cloudera][HiveJDBCDriver](500164) Error initialized or created transport for authentication: Peer indicated failure: Unsupported mechanism type PLAIN.
at com.cloudera.hiveserver2.hivecommon.api.HiveServer2ClientFactory.createTransport(Unknown Source)
at com.cloudera.hiveserver2.hivecommon.api.ZooKeeperEnabledExtendedHS2Factory.createClient(Unknown Source)
...
I thought, that it is missing AuthMech attribute and added AuthMech=1 to the URL. Now I am getting:
java.sql.SQLNonTransientConnectionException: [Cloudera][JDBC](10100) Connection Refused: [Cloudera][JDBC](11640) Required Connection Key(s): KrbHostFQDN, KrbServiceName; [Cloudera][JDBC](11480) Optional Connection Key(s): AsyncExecPollInterval, AutomaticColumnRename, CatalogSchemaSwitch, DecimalColumnScale, DefaultStringColumnLength, DelegationToken, DelegationUID, krbAuthType, KrbRealm, PreparedMetaLimitZero, RowsFetchedPerBlock, SocketTimeOut, ssl, StripCatalogName, transportMode, UseCustomTypeCoercionMap, UseNativeQuery, zk
at com.cloudera.hiveserver2.exceptions.ExceptionConverter.toSQLException(Unknown Source)
at com.cloudera.hiveserver2.jdbc.common.BaseConnectionFactory.checkResponseMap(Unknown Source)
...
But KrbHostFQDN is already specified in the principal property as required in the documentation.
Am I missing something or is this documentation wrong?
Below is the one of the similar kind of problem statement in Impala (just JDBC engine changes others are same) that is resolved by setting "KrbHostFQDN" related properties in JDBC connection string itself.
Try to use the URL below. Hopefully works for u.
String jdbcConnStr = "jdbc:impala://myserver.mycompany.corp:21050/default;SSL=1;AuthMech=1;KrbHostFQDN=myserver.mycompany.corp;KrbRealm=MYCOMPANY.CORP;KrbServiceName=impala"
I suppose that if you are not using SSL=1 but only Kerberos, you just drop that part from the connection string and don't worry about setting up SSL certificates in the java key store, which is yet another hassle.
However in order to get Kerberos to work properly we did the following:
Install MIT Kerberos 4.0.1, which is a kerberos ticket manager. (This is for Windows)
This ticket manager asks you for authentication every time you initiate a connection, creates a ticket and stores it in a kerberos_ticket.dat binary file, whose location can be configured somehow but I do not recall exactly how.
Finally, before launching your JAVA app you have to set an environment variable KRB5CCNAME=C:/path/to/kerberos_ticket.dat. In your java app, you can check that the variable was correctly set by doing System.out.println( "KRB5CCNAME = " + System.getenv( "KRB5CCNAME" ) ). If you are working with eclipse or other IDE you might even have to close the IDE,set up the environment variable and start the IDE again.
NOTE: this last bit is very important, I have observed that if this variable is not properly set up, the connection wont be established...
In Linux, instead MIT Kerberos 4.0.1, there is a program called kinit which does the same thing, although without a graphical interface, which is even more convenient for automation.
I wanted to put it in the comment but it was too long for the comment, therefore I am placing it here:
I tried your suggestion and got another exception:
java.sql.SQLException: [Cloudera]HiveJDBCDriver Error
creating login context using ticket cache: Unable to obtain Principal
Name for authentication .
May be my problem is, that I do not have environment variable KRB5CCNAME set.
I, honestly, never heard about it before.
What is supposed to be in that ticket file.
I do have, however, following line in my main method:
System.setProperty("java.security.krb5.conf", "path/to/krb5.conf");
Which is supposed to be used by
UserGroupInformation.loginUserFromKeytab(config.getProperty("login.user"), config.getProperty("keytab.file"));
to obtain the kerberos ticket.
To solve this issue update Java Cryptography Extension for the Java version that you use in your system.
Here's the link when you can download JCE for Java 1.7
Uncompress and overwrite those files in $JDK_HOME/jre/lib/security
Restart your computer.

Cant connect to mariadb from java - only with mysqldeveloper [duplicate]

I am trying to connect to a database in Mariadb through a simple java application but the connection is told to be unsuccessful and an Exception is thrown. I have done the similar connection using mysql and it was working correctly. The problem is maybe with the driver here.
try{
Class.forName("org.mariadb.jdbc.Driver");
Connection connection = DriverManager.getConnection(
"jdbc:mariadb://localhost:3306/project", "root", "");
Statement statement = connection.createStatement();
String uname="xyz",pass="abc";
statement.executeUpdate("insert into user values('"+uname+"','"+pass+"')");}//end of try block
I looked up the internet for the help and came by that driver class provided by the MariaDB Client Library for Java Applications is not com.mysql.jdbc.Driver but org.mariadb.jdbc.Driver! I changed it accordingly but it seems the problem is with the very first line inside the try block. The driver is not loading at all.
Also, I have added the mysql jar file to the libraries of my java application as in the screen-shot below. Please help me through this.
It appears that you are trying to use jdbc:mariadb://... to establish a connection to a MariaDB server instance using the MySQL JDBC Driver. That probably won't work because the MySQL JDBC Driver would use jdbc:mysql://..., regardless of whether it is connecting to a MySQL server or a MariaDB server. That is, the connection string must match the driver that is being used (rather than the database server being accessed).
The MySQL and MariaDB drivers are supposed to be somewhat interchangeable, but it only seems prudent to use the MariaDB connector when accessing a MariaDB server. For what it's worth, the combination of mariadb-java-client-1.1.7.jar
and
Connection con = DriverManager.getConnection(
"jdbc:mariadb://localhost/project",
"root",
"whatever");
worked for me. I downloaded the MariaDB Client Library for Java from here:
https://downloads.mariadb.org/client-java/1.1.7/
which I arrived at via
https://downloads.mariadb.org/
Additional notes:
There is no need for a Class.forName() statement in your Java code.
The default configuration for MariaDB under Mageia may include the skip-networking directive in /etc/my.cnf. You will need to remove (or comment out) that directive if you want to connect to the database via JDBC because JDBC connections always look like "network" connections to MySQL/MariaDB, even if they are connections from localhost. (You may need to tweak the bind-address value to something like 0.0.0.0 as well.)
An additional note:
Exploring the MariaDB JDBC driver, I found this inside the url parsing file:
Project: https://github.com/MariaDB/mariadb-connector-j.git
File: src/main/java/org/mariadb/jdbc/UrlParser.java
public static UrlParser parse(final String url, Properties prop) throws SQLException {
....
if (url.startsWith("jdbc:mysql:")) {
UrlParser urlParser = new UrlParser();
parseInternal(urlParser, url, prop);
return urlParser;
} else {
if (url.startsWith("jdbc:mariadb:")) {
UrlParser urlParser = new UrlParser();
parseInternal(urlParser, "jdbc:mysql:" + url.substring(13), prop);
return urlParser;
}
}
As you can see, the string "jdbc:mariadb:" is always replaced with "jdbc:mysql:" internally. So when it comes to the MariaDB driver, whether it is :mariadb: or :mysql: it always gets parsed as "jdbc:mysql:".
No difference.
if (url.startsWith("jdbc:mariadb:")) {
....
parseInternal(urlParser, "jdbc:mysql:" + url.substring(13), prop);
....

Connecting Java and Teradata: The UserId, Password or Account is invalid

I have been trying to connect to Teradata
Class.forName("com.teradata.jdbc.TeraDriver");
String connectionString = "jdbc:teradata://xxx.xxxxxx.com/database=xxxxxx, tmode=ANSI, charset=UTF8";
String user = "Rocket512";
String password = "aui8mn5";
Connection conn = DriverManager.getConnection(connectionString, user, password);
Got the following
Exception in thread "main" com.teradata.jdbc.jdbc_4.util.JDBCException: [Teradata Database]
[TeraJDBC 14.10.00.17] [Error 8017] [SQLState 28000] The UserId, Password or Account is invalid.
at com.teradata.jdbc.jdbc_4.util.ErrorFactory.makeDatabaseSQLException(ErrorFactory.java:300)
at com.teradata.jdbc.jdbc.GenericLogonController.run(GenericLogonController.java:666)
at com.teradata.jdbc.jdbc_4.TDSession.<init>(TDSession.java:216)
I know that the host is specified correctly since i did not get UnknownHost Exception.
Also I have double checked my userid and password are correct.
I ran query suggested by #beni23 (thank you)
select *
from dbc.logonoff
where logdate >= date '2013-10-31'
Here is the result that I got
What is Bad Password? I used SQL Assistant with this very password and it works great. Why cannot i connect with Java?
LDAP Authentication failures will not be captured in DBC.LogOnOff as a Bad Password event because the authentication doesn't take place on the database.
Typically the error message you are receiving, The UserId, Password or Account is invalid., is indicative of the user account being locked on the database.
SELECT U.UserName
, U.ProfileName
, U.DefaultAccount
, COALESCE(P.MAXLOGONATTEMPTS, S.MAXLOGONATTEMPTS) AS MaxLogonAttempts_
, U.LockedCount
, U.LockedDate
FROM dbc.UsersV U
LEFT JOIN
dbc.ProfileInfoV P
ON P.ProfileName = U.ProfileName
CROSS JOIN
dbc.SecurityDefaults S
WHERE UserName = 'Rocket512';
If LockedCount is not 0 than a failed logon attempt has occurred since the last successful logon to the database.
If LockedDate is not NULL it represents the date which the account was last locked.
MaxLogonAttempts_ will tell you how many times you can attempt to logon using database authentication (TD2) before the account is locked.
A couple of things I would suggest:
Remove whitespace between the parameters of connectString
Put the User and Password parameters in the connectString
Using original code above modify the connectString to add: ,ACCOUNT=$AMRWRW&DrT&r which should match what is returned by the query in my response above (I have added DefaultAccount).
EDIT: 11/12/13
May I suggest you download Teradata Studio Express and attempt to make a connection to the same Teradata system using JDBC much like you are here in your code. This may help shed light on the parameters you need to specify in your connection string in order to make the connection successful. You should be able to setup your connection parameters in Teradata Studio Express the same as you have here in your code and see if it works.
Using LDAP as the logon mechanism for a user that has not been granted the explicit right to logon with a NULL password has resulted in the error message `The UserId, Password or Account is invalid.'. I received this the other day using a privileged account without changing my logon mechanism from LDAP to TD2.
What does the following SQL return?
SELECT *
FROM DBC.LogonRulesV
WHERE UserName = 'Rocket512';
It may not return anything, which is okay. This simply means you ability to logon with that userid from any host on the system has not been explicitly granted or revoked.
EDIT: 05/22/18
The “Bad Password” event for an externally authenticated user may will appear in the event log when the provided password and the what is stored on the directory server do not match. In certain scenarios you can verify this by using ldapsearch from the PDN to submit an inquiry directly to the LDAP directory. You can find more details about using this command in the Security Administration manual. I’ve discovered this trying to triage a problem with a subset of user accounts that fail to authenticate to the directory. I felt it would be appropriate to update this answer with more details as my lead in statement at the top is not 100% accurate.
The following might not give you a solution, but might point you in the right direction. I think you'll want to check the dbc.logonoff table in teradata through a console to make sure that your user is not locked or get an idea whether your driver is hitting teradata.
select *
from dbc.logonoff
where logdate >= date '2013-10-31'
Reading this article Troubleshooting Security: The UserId, Password or Account is invalid. we can see the typical reason of this error.
Cause: LOGMECH=LDAP is specified, and the username/password credentials
are redundantly provided in the both LOGDATA and as separate
connection parameters.
Solution: Identify LDAP users via LOGDATA, or
via separate username/password parameters, but not both
simultaneously.
So, you should check this case. May be you can get connection without user/password
Perhaps you might have more luck with:
String driver = "com.teradata.jdbc.TeraDriver";
String conUrl="jdbc:teradata://xxx.xxxxxx.com/database=xxxxxx,USER=Rocket512,PASSWORD=aui8mn5,tmode=ANSI,charset=UTF8";
Class.forName(driver);
Connection dbConn = DriverManager.getConnection(conUrl);
If that doesn't work make sure to use the latest jdbc driver.
I had similar error and followed all the suggestions given in here. My account was not locked and I was able to connect to the DB with the same username and password, via SQL assistance editor.
The solution worked for me was adding following line in the connection string: LOGMECH=LDAP.
You need to know the logon mechanism for your Teradata, or you can reach out to your DBA team, as I did. So your connection string will look something like this:
String connurl="jdbc:teradata://xx/database=xx,USER=xx,PASSWORD=xx,tmode=ANSI,charset=UTF8,LOGMECH=LDAP";

Categories

Resources