I can figure out how to connect to an AS400 through jt400 with JNDI resources just fine:
Connection conn = null;
Statement stmt = null;
try {
Context ctx = (Context) new InitialContext().lookup("java:comp/env");
conn = ((DataSource) ctx.lookup("jdbc/AS400")).getConnection();
System.out.println(conn.getClientInfo());
stmt = conn.createStatement();
//SQL data fetch using the connection
ResultSet rs = stmt.executeQuery("SELECT * FROM LIBRARY.TABLE");
while (rs.next()) {
System.out.println(rs.getString("COLUMN1"));
}
conn.close();
conn = null;
}
catch(Exception e){System.out.println(e);}
However, another part of the application utilizes DataQueues (from the same jt400 library):
String queue = "/QSYS.LIB/" + libraryName +".LIB/" + queueName +".DTAQ";
try{
system = new AS400(server, user, pass);
DataQueue dq = new DataQueue(system, queue);
// Convert the Data Strings to IBM format
byte[] byteData = message.getBytes("IBM285");
dq.write(byteData);
System.out.println("Wrote to DataQueue");
}catch(Exception e){
e.printStackTrace();
System.err.println(e);
}finally{
// Make sure to disconnect
if(system != null){
try{
system.disconnectAllServices();
System.out.println("Disconnected from DataQueue.");
}catch(Exception e){
System.err.println(e);
}
}
}
Inside of this working code for DataQueues references server, user, pass, which isn't ideal.
I'd like to utilize the AS400 JNDI connection I already set up, but every example I see about connecting Java to DataQueues references an example much like this one.
The documentation all seem to point to AS400 system objects which are hard-coded references to servername, user, pass, etc.
Is there better way to utilize DataQueue() with a JNDI reference?
As assumed in the comments above, the DataQueue is not part of the JDBC connection at all, it can't be used to configure the connection for usage to reading and writing to a DataQueue. Since this is the case, it can't also share connection methods that JDBC uses even though the jt400 library connects with JDBC. A properties file or other server-based solutions is required unless a hard-coded connection is specified in the DataQueue/Java examples online (All 1 of them).
Related
I am making an FXML application with intelliJ and MYSQL in Java 11 that allows the user to create a database that has a name of their own choosing. The application:
recognises that the database doesn't yet exist
creates the database via a connect string that uses URL without a specfic DB name
connects to the new database and executes an sql.txt file thereby creating all the required tables.
This approach works save for the fact that when the final statement of the code below executes an automated alert pops up with:
"Cannot connect to database. Please close the program, check the driver is available and that the connection details are correct and then try logging on again".
It does this even though the new database with all required tables has been created and connected to.
Question: Is there anyway to disable this auto-generated message?
protected void execute() throws Exception {
// Connect using URL without DBNAME:This is a re-assignment of inherited value
conn = DriverManager.getConnection(DB_URL, USER, PASS);
// Create database at user request:
String sql = "CREATE DATABASE " + this.newDBName;
stmt = conn.prepareStatement(sql);
stmt.executeUpdate(sql);
StringBuilder sqlText = new StringBuilder();
File file = new File(this.getClass().getResource("createSQLScript.txt").toURI());
/*
Read in the Sql statement text file resource to create tables
using try-with resources and automatic resource closure.*/
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
sqlText.append(line);
}
}
// Set connection object to allow multiple queries in createSQLScript.txt
// A re-assignment of inherited value
conn = DriverManager.getConnection(DB_URL + this.newDBName + "?allowMultiQueries=true", USER, PASS);
stmt = conn.prepareStatement(sqlText.toString());
stmt.executeUpdate(sqlText.toString());
}
PS: DB_URL is - jdbc:mysql://localhost:3306/
This could be related to the fact that you created database in one connection and started accessing it in another connection without closing the previous one.
Connection and PreparedStatement are closable resources. You should always close them with try-finally or try-with-resources pattern, e.g.:
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS)) {
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
// execute stmt...
// populate database...
}
}
try (Connection conn = DriverManager.getConnection(
DB_URL + this.newDBName + "?allowMultiQueries=true", USER, PASS) {
// access newly created database...
}
I'm developing a desktop app to organize different events, thus creating a DB for each event. So far, I've managed to create a DB with whatever name the user wants, using a simple GUI.
However, I can't create tables nor columns for said database, even though it's exactly the same syntax I use in SQL Server Manager.
My code so far:
public static void creDB(String db_name, String table_name){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
conn = DriverManager.getConnection(connectionUrl);
String SQL = "CREATE DATABASE " + db_name;
stmt = conn.createStatement();
int result = stmt.executeUpdate(SQL);
String SQL3 = "USE " + db_name;
boolean ree = stmt.execute(SQL3);
String SQL4 = "GO";
boolean rr = stmt.execute(SQL4);
if (result == 0){
System.out.println("Se insertó :D!");
String SQL2 = "CREATE TABLE Pepe(Name_emp INT NOT NULL PRIMARY KEY)";
int res = stmt.executeUpdate(SQL2);
if (res == 0)
System.out.println("GRACIAS DIOS");
}else
System.out.println("Raios shico");
}catch (Exception e) {e.printStackTrace();}
finally {
if (rs != null) try {rs.close();} catch (Exception e) {e.printStackTrace();}
if (stmt != null) try {stmt.close();} catch (Exception e) {e.printStackTrace();}
if (conn != null) try {conn.close();} catch (Exception e) {e.printStackTrace();}
}
}
The error I get is when I try to actually use the DB, using the use [DB name] go; I tried already using that same syntax in one single SQL statement, however it didn't work, so I tried doing it separately and got this error:
com.microsoft.sqlserver.jdbc.SQLServerException: Could not find stored procedure 'GO'.
I know the code above looks like a mess, and it is, but it's just for testing purposes since I'm new to doing DB-related projects with Java; I mixed-matched some of the concepts of this site, which were successful up until the creation of the tables.
I know there's a better way of managing several databases, but as I said, I'm just starting so any advice would be greatly appreciated.
You should not use statements like USE <dbname> when using JDBC, it may lead to unexpected behavior because parts of the driver may still use metadata for the original connected database. You should either use setCatalog on the current connection to switch databases or create an entirely new connection to the new database.
In short, after creating the database, you should use:
conn.setCatalog(db_name);
That's it.
Also, go is not part of the SQL Server syntax, it is only used by tools like the Management Studio, see What is the use of GO in SQL Server Management Studio & Transact SQL? The equivalent in JDBC is to simply execute the statement.
Am getting the following error: com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "Connection reset by peer: socket write error."
import java.sql.*;
import com.microsoft.sqlserver.jdbc.*;
public class SQLDatabaseConnection {
// Connect to your database.
// Replace server name, username, and password with your credentials
public static void main(String[] args) {
String connectionString =
"jdbc:sqlserver://XXXXX.database.windows.net:1433;"
+ "database=VDB;"
+ "user=XXX#VVV;"
+ "password=XXXX;"
+ "encrypt=true;"
+ "trustServerCertificate=false;"
+ "hostNameInCertificate=*.database.windows.net;"
+ "loginTimeout=30;";
// Declare the JDBC objects.
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
// Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
connection = DriverManager.getConnection(connectionString);
// Create and execute a SELECT SQL statement.
String selectSql = "SELECT TOP 2 * from Application";
statement = connection.createStatement();
resultSet = statement.executeQuery(selectSql);
// Print results from select statement
while (resultSet.next()) {
System.out.println(resultSet.getString(2) + " "
+ resultSet.getString(3));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// Close the connections after the data has been handled.
if (resultSet != null) try {
resultSet.close();
} catch (Exception e) {
}
if (statement != null) try {
statement.close();
} catch (Exception e) {
}
if (connection != null) try {
connection.close();
} catch (Exception e) {
}
}
}
}
I'm only trying to do the "sample" connection snippet of code as referenced on the Azure site (which points to a MS entry), modified only to match my db and test table but without success.
Having reviewed all there is to know, I have:-
ensured that I'm using the right sqljdbc (I've tried all 4)
have the sqlauth.dll on the CLASSPATH
have set the sample up EXACTLY as shown; and incorporated the string that Azure offers.
I have tried various combinations of encrypt and trust without success. As I'm a newbie to Java and Azure, I'm reluctant and unsure how to fiddle with the JVM security settings.
I've proven that my machine can talk to the Azure database (through a VB ODBC connection); and I've tested with the firewall down.
Any thoughts?
I tried to reproduce the issue, but failed that I could access my SQL Azure Instance using the code which be similar with yours.
The difference between our codes is only as below, besides using the connection string of my sql azure instance.
Using the driver sqljdbc4.jar from the sqljdbc_4.0 link.
Using the code Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); to load MS SQL JDBC driver.
Not adding the sqlauth.dll file into the CLASSPATH.
Check my client IP which has been allowed by SQL Azure IP firewall.
Using the sql select 1+1 to test my code, and get the value 4 from code result.getInt(1).
That's fine for me. If you can supply more detals for us, I think it's very helpful for analysising the issue.
Hope it helps.
I created an application that writes data to the database every 5 minutes.
However after some time this error appears:
Error: Data source rejected establishment of connection, message from server: "Too many connections"
I've been searching around and tells you to close the connection to the database after every request side.
I tried this:
conexao.close();
But it gives me this error:
No operations allowed after conection closed.
I apologize if the question is not well formulated.
Thanks for the help
---------------------What I tried but didn't work---------------------------
Add
finally{
if(conexao!=null)
conexao.close();
}
Class.forName("com.mysql.jdbc.Driver");
Connection conexao = (Connection) DriverManager.getConnection("jdbc:mysql://localhost/bdTeste", "root", "root");
Statement stm = conexao.createStatement();
BufferedReader reader = new BufferedReader(new FileReader("C:/Users/RPR1BRG/Desktop/test.txt"));
String dados[] = new String[6];
String linha = reader.readLine();
while (linha != null) {
StringTokenizer st = new StringTokenizer(linha, ";\"");
dados[0] = st.nextToken();
dados[1] = st.nextToken();
dados[2] = st.nextToken();
dados[3] = st.nextToken();
dados[4] = st.nextToken();
dados[5] = st.nextToken();
DateFormat dateFormat = new SimpleDateFormat("d-M-yy");
PreparedStatement stmt = (PreparedStatement) conexao.prepareStatement("replace into registos"
+ " (data_registo, hora_registo, IdSensor, Temperatura, Humidade, pt_orvalho) values (?,?,?,?,?,?)");
try {
stmt.setDate(1, new java.sql.Date(dateFormat.parse(dados[0]).getTime()));
stmt.setString(2, dados[1]);
stmt.setString(3, dados[2]);
stmt.setString(4, dados[3]);
stmt.setString(5, dados[4]);
stmt.setString(6, dados[5]);
} catch (java.text.ParseException ex) {
Exceptions.printStackTrace(ex);
}
stmt.executeUpdate();
linha = reader.readLine();
PrintWriter writer = new PrintWriter("C:/Users/RPR1BRG/Desktop/test.txt");
writer.print("");
writer.close();
Verifica();
}
} catch (ClassNotFoundException | SQLException | IOException e) {
System.err.println("Erro: " + e.getMessage());
}finally{
if(conexao!=null)
conexao.close();
}
This kind of problem arises when you are NOT properly closing the connection after usage.
Please use finally block after catch to close the connections appropriately. This is because to ensure that the connection gets closed properly even when there is an unexpected exception or error. Please note that statements inside finally block gets executed always. it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break
Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.
As you have asked in comment, I have added the code sample to demonstrate practically!
Connection con = null
try{
//Establishing connection to datasource
con = DBConnection.getConnection();
//perform DB operations
...
...
...
}catch(SQLException sqlEx){
/*To catch any SQLException thrown during DB
*Operations and continue processing like sending alert to admin
*that exception occurred.
*/
}finally{
/*This block should be added to your code
* You need to release the resources like connections
*/
if(con!=null)
con.close();
}
Please note that the declaration of Connection variable should be in proper scope to close it in finally block.
Hope this helps!
This may be because of the configured max_connections is not suitable with the Connection Pool size set in JDBC or number of connections you open against DB.
to check number of max_connections in mysql:
show variables like 'max_connections';
make sure you have proper value of opened connections with the DB Max connections.
As from Java 7, java.sql.Connection is AutoCloseable. From now on, you can write your code like this:
try(Connection con = (Connection) DriverManager.getConnection(url, username, pazzword)) {
//your statements
}catch(RuntimeException e) {
}
Restart apache tomcat server will work. This worked for me.
Welcome
I have an app that I'm connecting to a MySQL database. It loses connection in the middle of the night and then spouts about null connections and JDBC hasn't received messages in X seconds.
I call getConnection() before I do anything that requires communication with the SQL server.
This is my getConnection() method:
private Connection getConnection() {
try {
if (connection != null) {
if (connection.isClosed() || !connection.isValid(10000)) {
this.initializeRamsesConnection();
}
} else {
this.initializeRamsesConnection();
}
} catch (Exception e) {
debug("Connection failed: " + e);
}
return connection;
}
In the initializeRamsesConnection() method I put the password and so on information into a string and then I create the connection in the standard JDBC way.
Then I call this method:
private Connection getConnectionFromConnectionString() {
Connection con = null;
String driver = "com.mysql.jdbc.Driver";
try {
Class.forName(driver);//jdbc sorcery
//if there is no connection string
if (getConnectionString() == null) {
HMIDatabaseAdapter.debug("No connection string");
}
//makes a string out of the values of db/host
String str = getConnectionString();
//if there is no driver
if (driver == null) {
debug("" + ": " + "No driver");
}
//Tries to make a connection from the connection string, username, and the password.
con = DriverManager.getConnection(str, username, password);
//if for some reason the connection is null
if (con == null) {
HMIDatabaseAdapter.debug("CONNECTION IS NULL, WHAT?");
}
} catch (Exception ex) {
HMIDatabaseAdapter.debug("getConnection() " + ex);
}
return con;
}
What can I change in either of these methods to accommodate losing connection?
This is not the correct way of retrieving a connection. You're retrieving the connection and assigning it as an instance (or worse, static) variable of the class. Basically, you're keeping the connection open forever and reusing a single connection for all queries. This may end up in a disaster if the queries are executed by different threads. Also, when it's been kept open for too long, the DB will reclaim it because it assumes that it's dead/leaked.
You should acquire and close the connection in the shortest possible scope. I.e. in the very same try block as where you're executing the query. Something like this:
public Entity find(Long id) throws SQLException {
Entity entity = null;
try (
Connection connection = dataSource.getConnection(); // This should return a NEW connection!
PreparedStatement statement = connection.prepareStatement(SQL_FIND);
) {
statement.setLong(1, id);
try (ResultSet resultSet = preparedStatement.executeQuery()) {
if (resultSet.next()) {
entity = new Entity(
resultSet.getLong("id"),
resultSet.getString("name"),
resultSet.getInt("value")
);
}
}
}
return entity;
}
If you worry about connecting performance and want to reuse connections, then you should be using a connection pool. You could homegrow one, but I strongly discourage this as you seem to be pretty new to the stuff. Just use an existing connection pool like BoneCP, C3P0 or DBCP. Note that you should not change the JDBC idiom as shown in the above example. You still need to acquire and close the connection in the shortest possible scope. The connection pool will by itself worry about actually reusing, testing and/or closing the connection.
See also:
Am I Using JDBC Connection Pooling?
JDBC MySql connection pooling practices to avoid exhausted connection pool
Where in your code are the errors on losing connection coming from? This would probably be the best place to start.
Off the top of my head (and I may be wrong), JDBC connections will only close on an actual fatal error, so you won't know they've failed until you try to do something.
What I've done in the past is to invalidate the connection at the point of failure and retry periodically.
Maybe this is what you are looking for:
http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html
For java see autoReconnect:
http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-configuration-properties.html