Sometimes when I call connect() on a third-party proprietary JDBC driver, it never returns and a stack trace shows that it is stuck waiting for a socket read (usually). Is there a generic way to forcibly cancel this operation from another thread? It's a blocking I/O call so Thread.interrupt() won't work, and I can't directly close the socket because I don't have access to it since it's created inside the proprietary code.
I'm looking for generic solutions because I have a heterogeneous DB environment (Oracle, MySQL, Sybase etc). But driver-specific suggestions are also welcome. Thanks,
There is no standard JDBC interface to set connection or read timeouts, so you are bound to use proprietary extensions, if the JDBC driver supports timeouts at all. For the Oracle JDBC thin driver, you can e.g. set the system properties "oracle.net.CONNECT_TIMEOUT" and or "oracle.jdbc.ReadTimeout" or pass a Properties instance to DriverManager.getConnection with these properties set. Although not particulary well documented, the Oracle specific properties are listed in the API documentation.
For other JDBC drivers, the documentation should contain the relevant references.
Ah ... the joys of using closed-source libraries ...
If interrupt() doesn't work, and you cannot set some kind of timeout, then I think there is no safe way to do it. Calling Thread.kill() might do the job, but the method is deprecated because it is horribly unsafe. And this is the kind of scenario where the unsafe-ness of Thread.kill() could come back and bite you.
I suggest that you simply code your application to abandon the stuck thread. Assuming that your application doesn't repeatedly try to connect to the DB, a stuck thread isn't a huge overhead.
Alternatively use a better JDBC driver. (And on your way out of the door, complain to the supplier about their driver being too inflexible. There is a slight chance that someone might listen to you ...)
At least one JDBC driver (not one of those you listed, though) will cleanly close the connection if the thread this connection attempt is running on is interrupted. I don't know if this will work for all drivers though.
This is a problem with Java, not the JDBC driver. In certain circumstances, the socket connect call ignores the timeout parameters and can take minutes to return. This happens to us when firewall blocks the port. It happens to all TCP connections (HTTP, RMI).
The only solution I find is to open connection in a different thread like this,
private static final ExecutorService THREADPOOL
= Executors.newCachedThreadPool();
private static <T> T call(Callable<T> c, long timeout, TimeUnit timeUnit)
throws InterruptedException, ExecutionException, TimeoutException
{
FutureTask<T> t = new FutureTask<T>(c);
THREADPOOL.execute(t);
return t.get(timeout, timeUnit);
}
try {
Data data = call(new Callable<Data>() {
public Data call() throws Exception
{
// Open connection, get data here
return data;
}, 2, TimeUnit.SECONDS);
} catch (TimeoutException e) {
System.err.println("Data call timed-out");
}
Related
I'm trying to set up a service which listens to a RabbitMQ server and I've set up code using the RabbitMQ Sample code from Github, which includes the following try-with-resources block
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
// code here
}
When I use the same code and build and run this service using java -cp myJar.jar MyService, it just starts and ends immediately (and echo $? returns 0)
However, if I replace the block with the following, then it works fine with the same command, and I'm able to start a listener to a RabbitMQ instance
try {
Connection connection = factory.newConnection();
Channel channel = connection.createChannel());
// code here
}
The same happens even when I create database connections
try (Connection connection = dataSource.getConnection()) {
//code here
}
fails but
try {
Connection connection = dataSource.getConnection();
//code here
}
works fine, and allows me to use the connection to make entries into the DB as well.
Why is this happening? I'm using OpenJDK 11.0.2 and this service is standalone, but the rest of the codebase is a JAX-RS driven Rest API if it helps.
The try-with-resources construct closes the resources when the block exits. Your basic try block code doesn't close anything. That's the difference between the two.
When you use try-with-resources, you need to actually DO something with the resource.
If you're writing code where the resource you are opening needs to be 'long lived', then try-with-resources is not the right construct (though, generally, that means the class you're writing should itself be AutoClosable).
When using any concept in programming you have to understand what you are doing!
The whole point of try-with-resource is that the resources are guaranteed to be closed when the try block ends.
But note: just using a try block is not sufficient. Such critical resources, like a database connection require distinct and intentional life cycle management. In other words: you should keep such resources around exactly as long as you need them. And you better make sure that you don't mistakenly forget to close a resource when it is no longer required!
Thus you should not lightheartedly give up on try-with-resource. Rather make sure that code that requires such a resource gets called within the scope of such a try-with-resource block!
I am using the following code to connect to a firebird database
public static Connection dbStatic;
...
public void getConnection(){
FBWrappingDataSource DataSource = new FBWrappingDataSource();
DataSource.setDatabase("localhost/3050:C:/MyDatabase.FDB");
DataSource.setDescription("TNS Development Database");
DataSource.setType("TYPE4");
DataSource.setEncoding("ISO8859_1");
DataSource.setLoginTimeout(10);
try {
dbStatic = DataSource.getConnection("UserName", "Password");
} catch (SQLException e) {
e.printStackTrace();
}
}
...and the following to disconnect:
...
dbStatic.close();
...
I am using Firebird 2.1 runing on a Windows 7-32 bit machine, with Java verstion 1.7, Jaybird version 2.2.8, Tomcat version 7.xx running on Win7-32bit, Browser is Chrome version something or other (newish) running Win XP SP3.
I use a third party tool called IBExpert to look at the number of connections and/or I run this statement:
select * from mon$attachments;
When I look at the number of connections to the database after the .close() statement runs the number does not decrease. Why is that? The number of connections do decrease if I wait long enough, or if the Tomcat server is restarted. Closing the browser does not affect the connections.
As Andreas already pointed out in the comments, FBWrappingDataSource is a connection pool. This means that the pool keeps physical connections open, and it hands out logical connections backed by the physical connections in the connection pool. Once you call close() on that logical connection, the physical connection is returned to the pool as available for reuse. The physical connection remains open.
If you want to close all connections, you need to call FBWrappingDataSource.shutdown(). This closes all physical connections that are not currently in use(!), and marks the data source as shutdown.
However, everything in package org.firebirdsql.pool should be considered deprecated; it will be removed in Jaybird 3. See Important changes to Datasources
If you just want a data source, use org.firebirdsql.pool.FBSimpleDataSource (with Jaybird 3 you will need to use org.firebirdsql.ds.FBSimpleDataSource instead).
If you want connection pooling, use a third party connection pool library like HikariCP, DBCP or c3p0.
That said, I want to point out several things you should consider:
Jaybird 2.2.8 is not the latest version, consider upgrading to 2.2.12, the current latest release of Jaybird.
Using a static field for a connection is generally not a good idea (especially with a web application), consider your design if that is really what you need. You might be better off making a data source the static field, and obtain (and close!) connections for a unit of work (ie: one request). It might also indicate that it would be simpler for you to just use DriverManager to create the connection.
Naming conventions: your variable DataSource should be called dataSource if you follow the common Java conventions
setLoginTimeout(Integer.parseInt(10)) should lead to a compilation error, as there is no method Integer.parseInt that takes an int, and the method itself already accepts an int.
A console application executing under:
1). Multiple threads
2). Connection Pooling (as the database connections range could be 5 to 30) of type Microsoft Access using DBCP.
While executing this application at my end (not tested the database limit) it works fine. And whenever I try to introduce the same application on one of other machines it generates an error.
I'm wondering why this is happening as there is only the difference of machines here. So, it works perfectly at my end.
I don't know much about connection pooling but it seems whatever I have understood I have implemented as:
public class TestDatabases implements Runnable{
public static Map<String, Connection> correctDatabases;
#Override
public void run() {
// validating the databases using DBCP
datasource.getConnection(); // Obtaining the java.sql.Connection from DataSource
// if validated successfully °º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸ putting them in correctDatabases
}
}
The above case is implemented using ExecutorService = Number of databases.
Finally, I'm trying to put them in a static Collection of Type
Map<String, Connection> and making use of it throughout the application. In other words: I'm trying to collect the connectionString along with the Connection in a Map.
In other parts of my application I'm simply dealing with multiple threads coming along with the Connection URL. So, to perform any database operations I'm calling the
Connection con = TestDatabases.correctDatases.get(connectUrl);
For that machine, this application works fine for around ~5 databases. And the error is always getting generated when I'm trying to fire the query using above Connection (con) as stmt.executeQuery(query);
As, I'm not able to reproduce this issue at my end, it seems something is going-on wrong with the Connection Pooling or I have not configured my application to deal with Connection Pooling correctly.
Just for your information, I'm correctly performing Connection close in finally block where my application terminates and this Application is using Quartz Scheduler as well. For Connection Pooling, a call to the following from TestDatabases class is done for setUp as:
public synchronized DataSource setUp() throws Exception {
Class.forName(RestConnectionValidator.prop.getProperty("driverClass")).newInstance();
log.debug("Class Loaded.");
connectionPool = new GenericObjectPool();
log.debug("Connection pool made.");
connectionPool.setMaxActive(100);
ConnectionFactory cf = new DriverManagerConnectionFactory(
RestConnectionValidator.prop.getProperty("connectionUrl")+new String(get().toString().trim()),
"","");
PoolableConnectionFactory pcf =
new PoolableConnectionFactory(cf, connectionPool,
null, null, false, true);
return new PoolingDataSource(connectionPool);
}
Following is the error I'm getting (at the other machine)
java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver] System resource exceeded.
Following is the Database Path:
jdbc:odbc:DRIVER= {Microsoft Access Driver (*.mdb, *.accdb)};DBQ=D:\\DataSources\\PR01.mdb
Each of those database seems to be not much heavy (its ~ 5 to 15 MB of total size).
So, I'm left with the following solutions:
1). Correction of Connection Pooling or migrate to the newer one's like c3p0 or DBPool or BoneCP.
2). Introducing batch concept - in which I will schedule my application for each group of 4 databases. It could be very expensive to deal with as any time the other schedule may also collapse.
I’m pretty sure that this is Java related error but I can’t fathom out why.
Just done the migration to BoneCP which solved my problem. I guess due to multi-threaded environment the dpcp was not providing the connection from pool rather it was trying to hit the database again and again. Maybe I could have solved the dpcp issue but migrating to BoneCP also provides advantage of performance.
What's the connection timeout of a socket created with a connecting constructor?
In Java SE 6, the following constructors for Socket will connect the socket right away instead of you having to call connect on it after construction:
Socket(InetAddress address, int port)
Socket(InetAddress host, int port, boolean stream)
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
Socket(String host, int port)
Socket(String host, int port, boolean stream)
Socket(String host, int port, InetAddress localAddr, int localPort)
While it's nice and convenient and all that the Java SE folks created 500 ways of constructing a socket so you can just browse the list of 500 to find the one that sort of does what you want (instead of calling new Socket() followed by Socket#connect()), none of the docs of these constructors says what the connection timeout is or whether/how they call connect(SocketAddress endpoint, int timeout).
Perhaps the stuff in the constructor docs talking about createSocketImpl imply something about the timeout, or some docs somewhere else say it?
Anyone know what the actual connection timeout for any of these constructors is?
Background: Okay, assuming the spec is really ambiguous (I thought Java is portable?), I'm trying to figure out why a customer's code freezes at seemingly random times. I have some code that calls some open source library which calls one of these constructors. I want to know whether calling one of these constructors would have made the timeout infinite or very long. I don't know what version of the JDK the customer is using so it would be nice if the spec says the timeout somewhere. I guess I can probably get the JDK version from my customer, but it will probably be the closed source JDK. In that case, could I reverse-engineer the code in their version of the SE library to find out? Is it hard? Will I go to jail?
Java spec is bogus. It doesn't say what timeout is on any of those constructor so implementation could set timeout to 0.000000000001 nanoseconds and still be correct. Furthurmore: non finite timeout not even respected by vm implementations (as seen here) so look like spec doesnt even matter cause noone followed it.
Conclusion: You have to read closed source binary of customer JVM (probably illegal but you have to do what you have to do), also OS socket doc.
Even though Java docs says the timeout is infinite, it actually means that JVM will not impose any timeout on the connect operation, however OS is free to impose timeout settings on any socket operations.
Thus the actual timeout will be dependent on your OS's TCP/IP layer settings.
A good programming practice is to set timeouts for all socket operations, preferably configurable via configuration file. The advantage of having it configurable is that depending on the network load of the deployment environment, the timeout can be tweaked without re-building/re-testing/re-releasing the whole software.
Looking at the code of Socket in OpenJDK 6-b14, you can see that these constructors call connect(socketAddress, 0), which means an infinite timeout value.
According to the sources (I'm looking at 1.5_13 here, but there shouldn't be a difference), the different Socket constructors all call Socket(SocketAddress, SocketAddress, boolean) which is defined as:
private Socket(SocketAddress address, SocketAddress localAddr,
boolean stream) throws IOException {
setImpl();
// backward compatibility
if (address == null)
throw new NullPointerException();
try {
createImpl(stream);
if (localAddr == null)
localAddr = new InetSocketAddress(0);
bind(localAddr);
if (address != null)
connect(address);
} catch (IOException e) {
close();
throw e;
}
}
connect(SocketAddress) is defined as
public void connect(SocketAddress endpoint) throws IOException {
connect(endpoint, 0);
}
Hence, infinite timeout (as #Keppil already stated).
The Socket class exists since Java 1.0, but at that time, it was only possible to create sockets, which were immediately connected and it was not possible to specify a connect timeout. Since Java 1.4, it has been possible to create unconnected sockets and then specify a timeout using the connect method. I assume that someone simply forgot to clarify the documentation of the "old" constructors, specifying that these still operate without an explicit timeout.
The documentation of the connect methods with timeout parameter reads that "a timeout of zero is interpreted as an infinite timeout". This is actually incorrect as well, since it only means that no timeout is implied by the Java VM. Even with a timeout of 0, the connect operation may still timeout in the operating system's TCP/IP stack.
It's platform-dependent but it's around a minute. The Javadoc for connect() is incorrect in stating that it is infinite. Note also that the connect() timeout parameter can only be used to decrease the default, not increase it.
My team has to make some changes and renew an old web application. This application has one main thread and 5 to 15 daemon threads used as workers to retrieve and insert data in a DB.
All those threads have this design (here simplified for convenience):
public MyDaemon implements Runnable {
// initialization and some other stuffs
public void run() {
...
while(isEnabled) {
Engine.doTask1();
Engine.doTask2();
...
Thread.sleep(someTime);
}
}
}
The Engine class provides a series of static methods used to maipulate other methods of DataAccessor classes, some of those methods been static:
public Engine {
public static doTask1() {
ThisDataAccessor.retrieve(DataType data);
// some complicated operations
ThisDataAccessor.insertOrUpdate(DataType data);
}
public static doTask2() {
ThatDataAccessor da = new ThatDataAccessor();
da.retrieve(DataType data);
// etc.
}
...
}
DataAccessor classes usually interact with DB using simple JDBC statements enclosed in synchronized methods (static for some classes). DataSource is configured in the server.
public ThatDataAccessor {
public synchronized void retrieve(DataType data) {
Connection conn = DataSource.getConnection();
// JDBC stuff
conn.close();
}
...
}
The problem is that the main thread needs to connect to DB and when these daemon threads are working we run easily out of available connections from the pool, getting "waiting for connection timeout" exceptions. In addition, sometimes even those daemon threads get the same exception.
We have to get rid of this problem.
We have a connection pool configured with 20 connections, and no more can be added since that "20" is our production environment standard. Some blocks of code need to be synchronized, even if we plan to move the "synchronized" keyword only where really needed. But I don't think that it would make really the difference.
We are not experienced in multithreading programming and we've never faced this connection pooling problem before, that's why I'm asking: is the problem due to the design of those threads? Is there any flaw we haven't noticed?
I have profiled thread classes one by one and as long as they are not running in parallel it seems that there's no bottleneck to justify those "waiting for connection timeout".
The app is running on WebSphere 7, using Oracle 11g.
You are likely missing a finally block somewhere to return the connections back to the pool. With hibernate, I think this is probably done when you call close() or possibly for transactions, when you call rollback(). But I would call close anyway.
For example, I wrote a quick and dirty pool myself to extend an old app to make it multithreaded, and here is some of the handling code (which should be meaningless to you except the finnally block):
try {
connection = pool.getInstance();
connection.beginTransaction();
processFile(connection, ...);
connection.endTransaction();
logger_multiThreaded.info("Done processing file: " + ... );
} catch (IOException e) {
logger_multiThreaded.severe("Failed to process file: " + ... );
e.printStackTrace();
} finally {
if (connection != null) {
pool.releaseInstance(connection);
}
}
It is fairly common for people to fail to use finally blocks properly... For example, look at this hibernate tutorial, and skip to the very bottom example. You will see that in the try{} he uses tx.commit() and in the catch{} he uses tx.rollback(), but he has no session.close(), and no finally. So even if he added a "session.close()" in try and in catch, if his try block threw something other than a RuntimeException, or his catch caused an additional Exception before the try or a non-HibernateException before the rollback(), his connection would not be closed. And without session.close(), I don't think that is actually very good code. But even if the code is seemingly working, a finally gives you assurance that you are protected from this type of problem.
So I would rewrite his methods that use Session to match the idiom shown on this hibernate documentation page. (and also I don't recommend his throwing a RuntimeException, but that is a different topic).
So if you are using Hibernate, I think the above is good enough. But otherwise, you'll need to be more specific if you want specific code help, but otherwise the simple idea that you should use a finally to ensure the connection is closed is enough.