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.
Related
I am exploring ways to connect to a SQL database using JDBC in Java and interact with it. Problem is no matter how I follow the syntax to make such connection it does not let me to connect to that instance of SQL Server on my laptop. I have seen other people being able to run such instances on their localhost instead and be able to connect to it via JDBS but I could not find any walkthroughs as how I can do the same. Any help with it will be greatly appreciated. Here is the connection I have on my laptop:
And here the JDBC connection URL that I try to make based on this on my code:
package helpers;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DbHandler {
private static final String connectionUrl = "jdbc:sqlserver://LAPTOP-KAQ3H6IG//SQLEXPRESS:1433;database=pub;user=MyUserName;password=MyPassword";
public static void addNewJobWithName(String jobName) {
try (Connection connect = DriverManager.getConnection(connectionUrl)) {
connect.createStatement().execute("INSERT INTO [pub].[dbo].[jobs] (job_id, job_desc, min_lvl, max_lvl) VALUES (2,'QA3', 50, 100);");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
And the error I receive:
The TCP/IP connection to the host LAPTOP-KAQ3H6IG//SQLEXPRESS, port 1433 has failed. Error: "LAPTOP-KAQ3H6IG//SQLEXPRESS. Verify the connection properties. Make sure that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. Make sure that TCP connections to the port are not blocked by a firewall.". at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:237)
Thanks in advance for your help
Did a combination of things based on the comments made here and some other posts I read on stack overflow regarding other things to do to fully solve this problem here are the things that I did:
Changed my connection URL string to this:
"jdbc:sqlserver://localhost:1433;database=pub;user=MyUserName;password=MyPassword;encrypt=true;trustServerCertificate=true";
On SQL Server configuration manager clicked on 'SQL Server Network Configuration' and enabled 'Named Pipes' and 'TCP/IP' in 'Protocols for SQLEXPRESS' (where my local MSSQL instance is setup).
Clicking on TCP/IP in the same window, switched to the IP Address tab and entered '1433' as the port number for the IPAII section right at the end of the list (Leave the other port sections empty).
Restarted SQL Server (SQLEXPRESS) from the list of services in Windows.
Hope it can help other people having the same problem as well.
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.
I am learning Java and trying to put together a simple App containing a few jTables connected to database that can be updated etc. To do this I have created a database with a few tables through Netbeans which I understand (and wish) to be embedded in the final distributable app.
I am following the Programming Knowledge tutorials on Youtube to create most of the GUI. Everting is OK as long as I open the Services tab on Netbeans and manually right-click my database(testDB) and click Start Server. Then when I run the following code I get a successful connection:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
try{
//Register JDBC driver
Class.forName("org.apache.derby.jdbc.ClientDriver");
//Open a connection
String DB_URL = "jdbc:derby://localhost:1527/testDB";
String u_name = jTextField1.getText();
String p_word = jPasswordField1.getText();
conn = DriverManager.getConnection("jdbc:derby://localhost:1527/testDB",u_name,p_word);
JOptionPane.showMessageDialog(null,"Details Correct - Connection established");
Close_me();
Open_Table_GUI(u_name,p_word);
}
catch(ClassNotFoundException | SQLException e){
System.out.println(e);
}
}
However if I run that code WITHOUT manually clicking on start server I get the following:
java.sql.SQLNonTransientConnectionException: java.net.ConnectException : Error connecting to server localhost on port 1,527 with message Connection refused.
I have read the apache documentation and due to my level of inexperience I am not getting anywhere.
I have also checked out the answers to similar connection questions on here but again I can't seem to relate the issue in a way that works.
The ultimate goal for me is to have an app I can distribute to run on windows machines that will have the database/tables all included individually editable etc. I would hope to eventually create a database that resides on a shared drive and each individual can connect to automatically - but that's way down the line for now.
My request here is that someone can help me understand what I need to change in my code so that the "Start Server" is automatically done.
Thanks in advance for nay response.
OK guys so I found code that seems to work for me from a question asked on here by LMS
private void setup(){
try{
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
connection=DriverManager.getConnection("jdbc:derby:sheet;create=true","test","1234");
statement=connection.createStatement();
}
catch(ClassNotFoundException cnf){
System.out.println("class error");
}
catch(SQLException se){
System.out.println(se);
}
}
If anyone cares to link me to a reason why this in fact works that would be great, I'm assuming the Embedded driver doesn't go through the port and just looks within the project??
Anyway initially this seems to be solved!!
Please check your Server setting i.e.
-username and pwd in your program
and check that did you start the Derby server and is it listening at port 1527?
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);
....
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