I am trying to modularize my code but it involves passing around my object that implements AutoCloseable. Let say I have two public methods foo1 and foo2:
public class MyClass {
public void foo1() {
// Connection implements AutoCloseable
try (Connection conn = createConnection()) {
foo2(conn);
// is the connection closed or the behavior unpredictable?
conn.doSomethingElse();
}
}
public void foo2(Connection conn) {
try (conn) {
// do something with the Connection
}
}
}
I want to call foo2 from foo1, but also allow other classes to use foo2 separately.
public class OtherClass {
public void doSomething() {
MyClass myClass = new MyClass();
myClass.foo2(createConnection());
}
}
Does this lead to the connection being closed in foo1() after the call to foo2? Or should I put the try-with-resources in the calling methods (such as the doSomething() in OtherClass)?
Your foo1 method closes the connection after foo2 has used it. There is no need for foo2 to close the connection and it shouldn't. You're making it have an unexpected side-effect. E.g. when you call conn.doSomethingElse() inside foo1, you will find it won't work because the connection has been closed by the call to foo2. It's a violation of the principle of least astonishment because the method name does not reveal this side-effect.
If you called it foo2AndCloseTheConnection then you make clear what it does, but I recommend following the rule of thumb that the method that creates the closeable should be the only one to close it. If you follow this consistently, you'll never need to look inside a function to see whether or not something you've opened is closed by that function. You'll simply close it yourself explicitly.
If you want foo2 to be called from other methods, you need to make those methods close the connection:
public void doSomething() {
MyClass myClass = new MyClass();
try (Connection connection = createConnection()) {
myClass.foo2(connection);
}
}
Yes, foo2 closes the connection so it will be invalid when control returns to foo1. Nothing unpredictable about it.
It's a good rule to have things closed by the same code that creates them. But it would be good to be able to nest these things and let them share the same connection and transaction. One solution would be to have each of these data accessing methods receive the connection as a parameter and have an outer layer that gets the connection and makes sure it gets closed.
You're basically trying to reinvent Spring a bit at a time. Spring gives you the ability to have services that can use the same connection and lets you control how and whether transactions are propagated between them. This is done using AOP to wrap objects with around advice that gets the current connection for the thread from a threadlocal data structure. Much easier to use spring (or whatever container).
Related
I'm writing some methods to deal with database operations. Each method first gets a connection, do the operations, and close the connection at end.
I wonder if Spring AOP can help handling the connection acquiring and closing. Specifically I want something like:
#Aspect
#Component
public class ConnAspect {
#Around("#annotation(connHandle)")
public void handleConnection(ProceedingJoinPoint pjp, ConnHandle connHandle) throws Throwable {
Connection conn = datasource.getConnection();
pjp.proceed(); // can pjp get variable conn?
conn.close();
}
}
#Component
public class DbOperation {
#ConnHandle
public void operation1(...) {
... // do some operation with conn
}
...
}
Is it possible to do so? Or should I turn to other solutions? Thanks for any hints and answers.
No, this is not possible, and the suggestions in the comments are not going to help you. You cannot magically inject a non-existent method parameter or local variable into a method. Besides, what you are trying to do is anti AOP: not to encapsulate your cross-cutting concern in an aspect, but somehow bleed aspect context into your application, which ideally should be unaware of the aspect and work without it. You should rather describe what you want to achieve instead of being fixated on a specific (bad) design you have dreamed up to implement your idea.
Besides, there are simpler, reflective ways for a method to fetch its own annotations than to abuse AOP for that purpose.
I'd like to decorate the interface PreparedStatement, in order to custom close it (just an example).
This means that I want to decorate an existing instance of PreparedStatement, thus, invoking other code, when close() is being invoked.
For that, I need to default implement all tens of methods of PreparedStatement decorator just to delegate the calls to the inner object, like done here. The downfall is that it's just a lot of work and code with little added value.
Another option is to try and use Java's Proxy and InvocationHandler in order to provide a default implementation that does the delegate for all the methods in a single method. If a custom method exists, the InvocationHandler, directs the call to it. See example here.
The problem with this solution is that the custom method cannot be marked as #Override and its signature cannot be checked for correctness, as it will require an abstract PreparedStatement, which the Proxy will not be able to instantiate.
So, can this be done? How?
* Must be able to implement using Java 7 max, but feel free to provide Java 8 answers.
As far as I understood you want to provide to the interface PreparedStatement concrete implementation. The only way I can think of is by creating abstract class that implements the interface. By doing so you don't need to implement all the methods from the interface and you'll have your desired implementation.
I'd try something like this:
public abstract class MyPreparedStatement implements PreparedStatement {
#Override
public void close() throws SQLException {
System.out.println("Closing");
}
public static void main(String[] args) throws SQLException {
Connection con = null;
MyPreparedStatement statement = (MyPreparedStatement) con.prepareStatement("sql");
}
}
Can you explain in clearer terms what the Proxy solution is lacking? Consider something like this, which relies on a AOP-esque 'hook':
final PreparedStatement original = ...;
final InvocationHandler delegator = new InvocationHandler() {
void onClose() {
/* do stuff */
}
Object invoke(final Object proxy, final Method method, final Object[] args) {
if (method.getName().equals("close")) {
onClose();
}
return method.invoke(original, args);
}
};
final PreparedStatement wrapped = (PreparedStatement) Proxy.newProxyInstance(this.getClass().getClassLoader(),
new Class<?>[] { PreparedStatement.class }, delegator);
If you don't have access to the methods in order to do the usual inheritance thing with them, you can accomplish what you are attempting to do with Aspect Oriented Programming, leveraging AspectJ or the Spring Framework aspect functionality to provide advice on your desired methods.
A simple aspect basically comes down to:
#Aspect
public class MyAspect {
#Pointcut("execution(* *(..))") //Replace expression with target method; this example
//will hit literally every method ever.
public void targetmethod() {}; //Intentionally blank.
//AspectJ uses byte code manipulation (or "black magic voodoo", if you
// will) to make this method a surrogate for any real one that matches the pointcut
#Before("targetmethod()") //Or #After, or #Around, etc...
public void doStuff() throws Throwable {
//Put your code here
}
}
Once you have your aspects together, add them to your aop.xml and weave your aspects (you can do this at compile time with appropriate build manager configuration, or at run time by running aspectjweaver with java -javaagent:/path/to/aspectjweaver.jar).
This does come with a disclaimer however: doing things like this to java.* classes allows you break things in new and interesting ways with all the side-effects you're introducing (in fact, AspectJWeaver refuses to weave into java.* classes by default, though you can override that setting). Be very aware of what you are doing, and use your aspects and aspected methods wisely.
I really like the java's try-with-resources behavior. I'm wondering is it possible to use the same behavior for an already constructed resource? for instance if I have to call open() on some resources can I call it as part of the try-with-resource and still have it be auto-closed, or even just pass the resource after I open it to have it close.
I suspect the answer is no, but just wanted to make sure I know of any useful syntax.
If the open() method returns an object which implements AutoCloseable and it is legal to close the resource after open() is called, this will work. No magic here.
try (MyAutoCloseable resource = Foo.open()) {
// .. do your work
}
You can do this... All that matters is that your resources are declared in the statement; which means you can do something like this:
final Foo toBeOpened = ...;
toBeOpened.open();
try (
final Foo opened = toBeOpened;
) {
/* work with opened */
}
I am trying to make automated error handling in java. Some one else could call my error handling method and it handles the errors for them. I am attempting to have it so if the class calling my method had a close() method I could call it and it would close everything preventing resource leaks. I tried something like this:
public void logError(Error e, Object obj){
obj.close();
}
The only problem is this will not run because object by default does not have a close() method. I could create my own object and have their class extend it but it would not work if they wanted to extend a different class.
You need an interface:
interface Closeable {
public void close();
}
Otherwise you could inspect the Object via reflection.
I think you have a design issue if you're closing resources in a logging method. As others have mentioned, use an interface and handle closing the resource elsewhere.
If you really want to proceed with this approach, you need to use reflection. The invoke call below will throw some exceptions that you'll need to catch.
public void logError(Error e, Object obj)
{
Method closeMethod = obj.getClass().getMethod("close", null)
if (closeMethod != null)
closeMethod.invoke(obj, null);
You could use the following:
public void logError(Error e, Closeable obj) {
//do your logging
obj.close();
}
public void logError(Error e, Object obj){
//do your logging
Method closeMethod = obj.getClass().getMethod("close", null);
if (closeMethod != null) {
//log that the method has a .close() method, but does NOT implement Closeable
}
}
This will ensure that first your logging will attempt to close a Closeable object. If that fails, it will fall back to the general Object implementation. And I have added reflection here only to do additional logging, it is not neccessary to use reflection at all in here and I think that you should not be calling close() manually on an object that does not implement Closeable.
For method overloading precedence refer to: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2
The answer should work as any object is more specific as Object, as long as it adds something to the functionality.
I have implemented a connection pool. All is good. Now If a client borrows a connection and even returns it to the pool but the client also keeps the reference of this connection with him. Now, if pool returns same connection to another client; this will lead to same connection being used by multiple people.
How can I avoid that ?
Do not return the underlying connection object, but another object which wraps it. Within that object (using some kind of private property) store the state of that object; is it still available for use, or has it been invalidated by being returned to the pool or some other condition like being timed out). Then you can intercept any method call that attempts to use it and check against its state. If it is no longer available for use, throw an exception.
The wrapped connection object will also need to be private, so that the client cannot access it directly.
You will have one wrapper per client, but two or more wrappers may share the underlying connection object. But because you are storing state per client, only one client can use the object at one time.
Edited to include an untested example - which now shows a big problem with my approach.
Assuming you are returning something which implements java.sql.Connection, you could return instances of the below class.
package same.package.as.your.pool; // so your pool has access to set isValidConnection
import java.sql.Connection;
class MyConnection implements Connection {
private Connection actualConnection;
private boolean isValidConnection = false;
MyConnection(Connection conn) {
// package acccess for pool class to create connection
actualConnection = conn;
isValidConnection = true;
}
public boolean getIsValidConnection() {
return isValidConnection;
}
void setIsValidConnection(boolean isValid) {
// pool class can call this to invalidate when returned to pool or timed out
isValidConnection = isValid;
}
// intercept java.sql.Connection methods, checking if connection is still valid first
// for example
PreparedStatement prepareStatement(String sql) {
if (! isValidConnection) {
// WHAT TO DO HERE?
}
return actualConnection.prepareStatement(sql);
}
// ... and the rest
First big problem is that - ideally you would throw an Exception from the methods like prepareStatement when the connection is no longer valid because it's been returned to the pool. But because you are constrained by the caught exceptions of the original interface (in this case, throws SQLException) you'd either need to throw an SQLException (yuk, it isn't really an SQLException) or an uncaught exception (yuk - client code would probably want to catch the case where the pooled connection is not longer valid) or something else :-)
Two other issues with the code above - package access to protect the methods meant to be only available to your pool code is not very robust. Maybe you could create the MyConnection code as some kind of inner class within your pool code. Finally, having to override all java.sql.Connection interface would be a pain.
}