I use JOOQ for querying my relational database, I've recently been looking at the connection handling and its confusing me a little. I've tried reading the JavaDoc and also this: When is a Connection closed when calling JooQ DSLContext's .close(), if at all? but its creating even more FUD for me.
Currently my code does this:
try (final Connection cn = pool.getConnection()) {
DSLContext dsl = DSL.using(cn, MARIADB);
// query stuff
}
Essentially I'm treating JOOQ as just a querier that doesn't do connection handling at all. I've never had problems with this code.
However, I do get warnings from IntelliJ saying that DSLContext is AutoClosable and should be handled by a try-with-resources. I know it doesn't have to in this case but my first question is 'Can it?'. Is it safe to replace the above code with this instead:
try (final DSLContext dsl = DSL.using(pool.getConnection(), MARIADB)) {
// query stuff
}
The other StackOverflow post said that you need to use close() on the DSLContext when you have created it using one of the helper methods. But what if you just passed the Connection object in? Will the close() still close my connection?
I also found that DSL has another using() that allows you to assign an entire DataSource. So instead I could also do this:
final DSLContext dsl = DSL.using(pool, MARIADB);
and then just leave out all the try-with-resources entirely. What are trade-offs here? Are there any even?
IntelliJ further complained about an UpdateQuery that has the AutoClosable interface (inherited from Query). Is it necessary to close my queries? I've always just called execute() and closed the underlying connection without problems.
What I am looking for is code that will satisfy these four requirements
It uses correct resource management
It uses JOOQ
The try-with-resources warning is turned on in the IDE
There are no warnings
The various pieces of code above all fail at least one of those requirements. But ultimately the connection handling doesn't matter that much because the query classes in JOOQ also generate tons of warnings.
The best way is indeed to turn the warning off, but then for JOOQ specifically using Intellij's exclusion rules. How to do this is mentioned in a comment on the page that Lukas linked too (https://blog.jooq.org/2015/12/02/a-subtle-autocloseable-contract-change-between-java-7-and-java-8/).
I'll just have to remember to do things the right way for JOOQ classes :)
Currently my code does this:
try (final Connection cn = pool.getConnection()) {
DSLContext dsl = DSL.using(cn, MARIADB);
// query stuff
}
That's correct usage.
Essentially I'm treating JOOQ as just a querier that doesn't do connection handling at all.
That's a correct assumption.
However, I do get warnings from IntelliJ saying that DSLContext is AutoClosable and should be handled by a try-with-resources
Many IDEs do this check, but it's usually best to turn them off. In Java 8+, you cannot reasonably expect an AutoCloseable to really need closing. One such example is Stream, which is AutoCloseable for those cases where it really does contain a resource, but mostly it doesn't.
This was a subtle API change in Java 8, leading to this warning in IDEs best being turned off (or you can maybe specify exceptions).
Your questions:
Is it safe to replace the above code with this instead:
try (final DSLContext dsl = DSL.using(pool.getConnection(), MARIADB)) {
// query stuff
}
Yes, you can do that. The DSLContext.close() call will only close resources that were created by DSLContext. In your case, it does not have any effect.
For the record, resourceful DSLContexts are created, e.g. by DSL.using(url, username, password)
and then just leave out all the try-with-resources entirely. What are trade-offs here? Are there any even?
All of this has really nothing to do with resources.
IntelliJ further complained about an UpdateQuery that has the AutoClosable interface (inherited from Query). Is it necessary to close my queries? I've always just called execute() and closed the underlying connection without problems.
turn off that warning! :-)
queries can be resourceful when calling Query.keepStatement(true)
Related
Our code has a commonly used utility that creates thread level global object. Say
GlobalObject.open(String ID);
And it will rely on explicitly ClobalObject.close(String ID); to make the object close(garbage collection).
And also, if the code is like:
GlobalObject.open(String ID);
//some computation
ClobalObject.close(String ID);
If there is Exception throw in the "some computation" part, a close statement will never reach and causing the memory leak.
Anyway can programmatically detecting whether the ClobalObject.close is there and explicitly in the finally block so it can always be executed?
Thanks
I think what you really need is a source code analyser like Findbugs (or it's successor SpotBugs) & PMD (don't choose, you need both, there is plugins for all popular IDEs), or just Sonar (which is basically a server designed to hold and display the results of those two, in which case you'll need to have continuous integration to make sure it gets updated often), so you can find programming mistakes like this one.However, I'll think you may have to create a custom rule for your case, which I don't know how hard it can be.
In case you really want to do it programmatically at runtime, you could do that with a Java agent, and JVMTI but it's going to be very complicated unless you are very familiar with all the concepts of the JVM.
Another idea, if you are okay for changing the architecture of your project a little, instead of having developers do GlobalState.open(String ID) and then close(String ID), use aspects. What I mean is create an annotation like #GlobalState(String ID) that will tell that before opening this method you must open ID and close it afterwards, this way you can have only one interceptor that will do the open() and close(), which make it easier for developers and safer. If ID is not a constant you can also have another annotation on one of the parameter, like #GlobalStateId that your interceptor can use to know which value to use for ID.
I have a DBconnector class that I've written. Here is an instance of it using an insert query method it has. Ignore the query for now:
ResultSet NewCustomer = db.executeInsert("SELECT s Bookings VALUES (surnameOut,'Nilsen', 'Johan', 'Bakken 2', 'Stavanger')");
At the moment the above line is getting a "Unhandled exception type SQLException" error. It suggests that I surround the above with a try/catch statement, or give the method that hold's the code a throws exception. I was hoping there was some way to sort it out from within the DBconnector class, so that I can maintain tiny, single lines for executing SQL queries. Is this possible?
Here is the code from the method executeInsert method:
public ResultSet executeInsert(String query)throws SQLException {
Statement s = null;
ResultSet rs = null;
try{
s = con.createStatement();
s.executeQuery(query);
rs = s.getResultSet();
}
catch(SQLException e){}
return rs;
}
I was hoping there was some way to sort it out from within the DBconnector class, so that I can maintain tiny, single lines for executing SQL queries.
So what do you want to happen when you've got a broken query (e.g. because you're trying to execute an insert which actually selects). Do you really want to just completely ignore the failure, without even logging it, as your current method does? That's almost never the right approach. In many cases, if a database query fails, you should abort whatever you're doing - the exception should bubble up the stack to some high level "unit of work" whether that's a request, a user action or whatever.
The reason for Java's checked exceptions is precisely to force you to think about how you want to handle errors - so don't ignore it, really think what you'd like to happen... and if this method doesn't have enough context to say (which it probably doesn't) you should let the exception bubble up, and force the callers to think.
This is (essentially) the old checked exceptions argument - some people love them, some people hate them (see here).
I, for one, don't like checked exceptions (Is it dangerous to disagree with Mr. Skeet # 415k reputation??!), so when I'm forced to deal with one, I generally use a try/catch and rethrow the error as a custom made subclass of RuntimeException. RuntimeExceptions don't need to be handled explicitly.
Spring, which is one of the most heavily used frameworks around, takes this approach.
When you use RuntimeExceptions, though, make sure that at some point you know where that exception is going to be handled. You never want it to go all the way to your end user and let them see a nasty stack trace.
To answer your question, your method in DBConnector explicitly says it throws a SQLException (even if it isn't). Because SQLException is a checked exception, you need to deal with it with whatever code calls it.
It sounds like this is not the case you want though. If you remove the throws SQLException , you can write your tiny SQL code. Be sure to take the advice of the other answers though because you are effectively ignoring problems which may not be a good thing.
I want to close statement automatically.
I want to achieve it by the technology of the following conditions.
java1.5
spring framework2.5
It seems not to close automatically in the setting of default though I think that transaction manager of spring automatically shuts statement.
I do not want to call close() of statement as much as possible in the method for maintainability.
Is there a method of statement's closing?
Moreover, is there an official site or document that shows the reason when there is no closing method?
The amount of coding increases if coming for all the methods to have to call close() of statement, and there is a problem that the possibility that the omission is generated goes out.
Moreover, I am making the framework. It wants to make the restriction as much as possible by such a reason and to make a little method.
If I understood your question right you can use the http://commons.apache.org/dbcp/ to do the closing for you, as far as I know this is the standard anyway so most likely you are already using it, as long as you use spring or jndi to provide your database connectivity.
In your configuration for the database connection configure
removeAbandoned=true
and
removeAbandonedTimeout=50
See http://commons.apache.org/dbcp/configuration.html (the lowest block) for details.
Be aware that you should a rather large connection pool if you rely on it to clean up your connections.
To the question on why there is no closing method: there is.
For Connections: http://download.oracle.com/javase/6/docs/api/java/sql/Connection.html#close()
For Statements: http://download.oracle.com/javase/6/docs/api/java/sql/Statement.html#close()
For ResultSets: http://download.oracle.com/javase/6/docs/api/java/sql/ResultSet.html#close()
closing a Connection will close all its Statements.
closing a Statement will close all its ResultSets.
After all, its no good style to do so. I recommend calling the close() by yourself and use the abandonment removal only to find the places where you forgot to do so by adding
logAbandoned=true
We've found a bug in old code where connections aren't being closed. It's an easy fix, but I'm wondering how we go about proving that it's fixed. There is a choice of using a connection pool or not. For the pooling use it would be easy to add monitoring for the pool, but when connections pooling is not used, how do we track those unclosed, orphaned connections? Is it just like any other memory leak?
The bug looks like basically a cut and paste error. We have a few classes that manage the DB connection, so it looks roughly like this:
OurDBConn conn1 = ConnectionManager.getConnection();
try {
// business logic
} catch () {
//
} finally {
ConnectionManager.returnConnection(conn1);
}
/// and then later in the same method
OurDBConn conn2 = ConnectionManager.getConnection();
try {
// business logic
} catch () {
//
} finally {
ConnectionManager.returnConnection(conn1); // NOTE Error: conn1 should be conn2
}
I don't know why the earlier coders didn't just reuse the original connection, but that's what it is
(begin edit/append)
Yes, the connection code is ours as well and so I can use the answers given.
However, I don't think I asked the right question, although the answers below answer the question I asked. I'm not sure what the right stackoverflow thing to do is; ask another question, or edit this one?
One of the question I should have asked is: how would these orphaned, un-closed connections manifest themselves in system performance? Also, since these connection objects exist only within the scope of a certain method, wouldn't the connections be eligible for garbage collection? And then if they are gc'ed, what is the effect of open connections being gc'ed?
(end edit)
Assuming the connection manager is also your own code, you could store the initialised connections (along with a stacktrace) in a map within the connection manager, and then remove them when they are returned. Thus at any point, the keyset of the map is the set of unreturned connections, and you can look up that value in the map in order to find the guilty bit of code that created them and never released them. (If the connection isn't a suitable map key you can probably use some kind of unique ID or connection number or whatever - the actual value doesn't matter so much as its presence).
Then just add some appropriate way to access this map on demand and you're good. Depending on your environment, adding a shutdown hook that dump the contents of the map to a file, and/or adding a JConsole interface to lookup the set of unclosed connections in running code, could both be good options.
If the connection manager isn't your code, you could still probably achieve the same thing using aspects.
You can implement custom mini-framework or use exisitng one as a thin wrapper on JDBC operations. For example there is a spring-jdbc module (mavenized) that covers all of the boilerplate error-prone code from developer.
You can check its usage examples and see that there is no initialization/cleanup at the client code at all! It uses 'template method' pattern, i.e. you just write essential data processing and don't bother with connections/statements/resultsets creation and closing. So, it becomes not possible to introduce the problem you talked at first.
Currently what i am doing for transaction management is:
Connection connection = getConnection();
connection.setAutoCommit(false);
updateTableX ( connection, ... );
updateTableY ( connection, ... );
connection.commit();
closeConnection();
I would like to know, if it is possible to avoid closing the connection in my 'updateTableX' method. Because if someone accidentally closes the connection then my updateTableY will not be having the connection and it will throw the exception.
Just discipline. In general, methods shouldn't try to take responsibility for closing things passed into them as parameters - with the exception of situations where you create a new object to wrap an existing one.
The way to avoid closing the connection in updateTableX is just to make sure you don't put a call to close() into the code. This is no different than any other bug really. How do you stop updateTableX from arbitrarily updating a different table, or throwing an exception, or doing anything else it's not meant to? Code reviews, unit tests, integration tests, manual testing etc...
I mean you could write a Connection implementation which wraps another connection and proxies all the methods through except close() but it sounds like a waste of time - if you don't trust the developers involved not to close the connection, do you trust them to get the rest of the code right?
Like Jon said, if you really want to forbit to call close() you could write a decorator implementation that forwards to your "real" Connection object. I don't post a code example because the Connection interface is too big. With modern IDEs however it is no problem to generate the code.
Recipe (presuming you're using Eclipse):
Create a class that implements Connection, but do not implement the methods
Create a field private Connection delegate;
Select the field name -> Source (Menu) -> "Generate Constructor using fields" -> make sure the field is selected and press ok
Select the field name -> Source (Menu) -> "Generate Delegate Methods..." -> check every method on you field
Change the implementation of the close() method to throw an UnsupportedOperationException
However like Jon said, I would really think about doing something like that. And maybe you just use a Object-Relational-Mapper (e.g. Hiberate) to encapsulate all of your Database access logic. An additional very helpful framework in this area is Spring, especially if you do not want to care about Connection and DataSource handling.
(I am unfamiliar with Java specifically)
Assuming you have some sort of database managing object, you could have it make sure it is connected before it attempts any operations.
You could try to restrict access to closing the connection but how would you decide if it should be closed, or if it's "accidental" (however you define that)?
I don't think what you are asking is possible.
You can technically make a copy of your connection object, but then what happens if the client programmer doesn't close the connection?