I have a class that extends from a package class that may or may not be in the classpath when the program is ran, it isn't called unless the dependency is met,
however it seems to annoy the java verifier that throws a NoClassDefFoundError on attempting to load the program,
Any way around this?
Any way around this?
In practice, no. The superclass has to be available on the classpath for the loading, linking and verification of the subclass to succeed. That has to happen before the class can be initialized, and instances of it created.
If you can't be sure that the superclass is going to be available, you need to remove all direct and indirect static dependencies on the subclass(es), and then load the subclasses dynamically using Class.forName(). That will fail if the superclass is "missing", but you will get a different exception (not an Error) and there is the possibility that your application can continue, if it is designed to cope with the missing classes.
Frameworks such as Spring which have "optionally used" code depending on other libraries, use a "Strategy pattern" to put that dependency-specific code into an "inner class" or into a separate class.
The outer class can be loaded & run fine; it's only when you try & instantiate the inner class that the NoClassDefFoundError will be thrown.
So the outer class typically tries (try-catch) instantiating one strategy to use, and then if that fails instantiates a fallback strategy.
public class MyService {
protected MyStrategy strategy;
// constructor;
// -- choose our strategy.
public MyService() {
try {
this.strategy = new ExternalLib_Strategy();
} catch (NoClassDefFoundError x) {
// external library not available.
this.strategy = new Standard_Strategy ();
}
}
// --------------------------------------------------------
protected interface MyStrategy {
public void doSomething();
}
protected static class ExternalLib_Strategy implements MyStrategy {
ExternalLib lib = org.thirdparty.ExternalLib.getInstance(); // linkage may
public void doSomething() {
// ... use the library for additional functionality.
}
}
protected static class Standard_Strategy {
public void doSomething() {
// ... basic/ fallback functionality.
}
}
}
As a work around to this problem, If your class (subclass) is available in the classpath, you can check whether the parent class is available in the classpath by loading the class file as a resource using the method ClassLoader.getResource(). This method will never throw a class not found exception. But this will return null if the class is not found. You can aviod using your class if the resource is null.
See this sample code below:
public class Test {
/**
* #param args
*/
public static void main(String[] args) {
Object instance = Test.class.getClassLoader().getResource("com/test/package/Base.class");
Derived derived = null;
if(instance !=null) {
derived = new Derived();
System.out.println(derived.getString()); // call the getString method in base class
}
else {
// The class is not available. But no Exception
System.out.println("No Hope");
}
}
}
Related
I would like to check, from an instance method of a non-final class, whether the constructors and initializers of that class and its chain of subclasses for the specific instance have already completed.
In the following example, I have a class Abstract, which can be used to implement an interface which allows listeners to be added (which, for simplicity, are just Runnable instances here) and which provides a method signalEvent() which calls all attached listeners.
abstract class Abstract {
protected final void signalEvent() {
// Check that constructs have run and call listeners.
}
public final void addListener(Runnable runnable) {
...
}
}
class Concrete extends Abstract {
Concrete() {
// Should not call signalEvent() here.
}
void somethingHappened() {
// May call signalEvent() here.
}
}
Now it is possible to call signalEvent() from within the subclass constructor, but there is no way that a listener has already been added by that time and the event would just be lost. In our code-base, once in a while, someone adds such a call and I would like to be able to catch such calls as early as possible (using an assert statement or similar).
Is it possible to check whether an instance method is being called, directly or indirectly, from the subclass constructor or initializer of the current instance or, alternatively, is it possible to check whether all constructors for an instance have been completed?
In short, there is no elegant Java mechanism that allows you to do that, but you may consider using a factory pattern. Instead of creating instances directly using new keyword, you could create a factory class, that takes care of creating the actual instance and invokes an additional "post-create" method, that lets the instance know it's been completely created.
If you're using some dependency injection like spring, you get that out of the box, but if not, a solution could look something like this:
interface PostConstruct { // the classes need to implement that
void postConstruct();
}
public class InstanceFactory {
public <T extends PostConstruct> T create(Class<T> clazz, Object... params) {
T instance = //create using reflection
instance.postConstruct();
return instance;
}
}
A solution to the problem to see if a method or code is being called from a constructor. The code below will print true and false respectivly but would be slow and not pretty at all.
I still believe it is not the right solution for the problem above. As Codbender said, better to check if a listener has been added or set a status variable which would be faster
Edit - fixed the issue that Codebender mentioned and also made sure to check back in the stack trace incase of being called a couple of methods deep
public class TestClass extends TestAbstract {
public TestClass() throws Exception {
submethod();
}
public void submethod() throws Exception {
System.out.println(isInConstructor());
}
public static void main(String[] args) throws Exception {
System.out.println(new TestClass().isInConstructor());
}
}
public class TestAbstract {
public boolean isInConstructor() throws Exception {
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
for (StackTraceElement element : elements) {
if (element.getMethodName().equals("<init>") &&
TestAbstract.class.isAssignableFrom(Class.forName(element.getClassName()))) {
return true;
}
}
return false;
}
}
Is it possible to instantiate and assign a singleton to a reference with Guice before creating the Module and pass that instance to the Module constructor be bound during configuration?
Here is an example of what I mean:
I have a method that allows me to create objects depending on a custom implementation of an interface which is being passed in constructor as an Optional (if the user won't provide a custom implementation, we will use the default one), which is being done by binding the interface to that particular implementation in the Module class. :
public static MyClass createMyClassObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
SpecialInterface specialInterfacebject;
if(customSpecialInterfaceObject.isPresent() {
specialInterfaceObject = customSpecialInterfaceObject.get()
} else {
/* here I would like to bind it to an instance of the DefaultSpecialInterfaceObject but can't really do something like:
Injector injector = Guice.createInjector(myClassModule);
DefaultSpecialInterface instance = injector.getInstance(DefaultSpecialInterface.class);
as the module is yet to be created */
}
MyClassModule myClassModule = new MyClassModule(specialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
return injector.getInstance(MyClass.class);
}
I'm currently using classes instead of instances to solve this problem, such as in the example below, but I don't quite like this solution. Would be happy to see a better way of doing it:
private static Class resolveSpecialInterfaceObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
Class specialInterfaceObjectClass;
if (customSpecialInterfaceObject.isPresent()) {
specialInterfaceObjectClass= customSpecialInterfaceObject.get().getClass();
} else {
specialInterfaceObjectClass = DefaultSpecialInterface.class;
}
return specialInterfaceObjectClass;
}
public abstract class MyClassModule extends AbstractModule {
private final Class<SpecialInterface> specialInterfaceObjectClass;
public MyClassModule(Class<SpecialInterface> specialInterfaceObjectClass) {
this.specialInterfaceObjectClass= specialIntefaceObjectClass;
}
#Override
protected void configure() {
bind(SpecialInterface.class).to(specialInterfaceObjectClass);
}
}
Edit, from a comment below:
one more thing- didn't want to make the question too long; actually, I also want to perform another operation on the resulting instance of SpecialInterface, but only if it is the instance of DefaultSpecialInterface and I don't think it should be done in the Module. I was thinking if I could just have this bean up and running before, such as in Spring, so I could just pass it to the Module, but also use it in another method call before?
Can you take the whole Optional and use bind(...).toInstance(...)?
public static MyClass createMyClassObject(
Optional<SpecialInterface> customSpecialInterfaceObject) {
MyClassModule myClassModule = new MyClassModule(customSpecialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
MyClassFactory instance = injector.getInstance(MyClassFactory.class);
return instance.createMyClassObject();
}
class MyClassModule extends AbstractModule {
private final Optional<SpecialInterface> customObject;
MyClassModule(Optional<SpecialInterface> customObject) {
this.customObject = customObject;
}
#Override public void configure() {
if (customObject.isPresent()) {
// Singleton by necessity: Guice doesn't know how to create another one.
bind(SpecialInterface.class).toInstance(customObject.get());
} else {
// Default scoped. Add ".in(Singleton.class)" if necessary.
bind(SpecialInterface.class).toInstance(DefaultSpecialInterfaceClass.class);
}
}
}
If you want to perform additional initialization on DefaultSpecialInterface and nothing else, you have a number of options:
If some kind of initialization is important for all implementations and likely too heavy to put into a class constructor, add an initialize method on your SpecialInterface. Make the custom one a no-op, and implement it for DefaultSpecialInterface.
If the initialization is unique to DefaultSpecialInterface, I see no reason why it shouldn't be in the Module. Write a #Provides method or bind to a Provider<SpecialInterface> that creates and initializes DefaultSpecialInterface correctly.
If your real goal is to keep the business logic out of a Module, you can do so by extracting it into a free-standing Provider or DefaultSpecialInterfaceFactory that is responsible for that.
Remember, Guice is responsible for feeding fully-constructed objects into your object graph, and that means that injecting a SpecialInterface should get a ready-to-use implementor of the SpecialInterface general contract. If Guice needs to perform some initialization to make that happen, it's not unreasonable to have it do so, and a Module isn't a bad place to do it.
The problem is: I have a class with only private constructor available (and I cannot modify it's source code), and I need to extend it.
Since reflections allow us to create instances of such classes whenever we want (with getting constructors and calling for newInstance()), is there any way to create an instance of an extended version of such class (I mean, really any way, even if it is against OOP)?
I know, it is a bad practice, but looks like I have no choice: I need to intercept some calls to one class (it is a singleton, and it's not an interface realization, so dynamic proxies do not work here).
Minimal example (as requested):
public class Singleton {
static private Singleton instance;
private Singleton() {
}
public static Singleton getFactory() {
if (instance == null)
instance = new Singleton();
return instance;
}
public void doWork(String arg) {
System.out.println(arg);
}}
all I want to do is to construct my own wrapper (like this one)
class Extension extends Singleton {
#Override
public void doWork(String arg) {
super.doWork("Processed: " + arg);
}}
and the inject it into Factory using reflection:
Singleton.class.getField("instance").set(null, new Extension());
But I do not see any way to construct such object cause its superclass's constructor is private. The question is "is that possible at all".
It is possible (but a bad hack) if
you have the source code of the class with the private constructors or you can reconstitute it from bytecode
the class is loaded by the application class loader
you can modify the jvm's classpath
You can than create a patch that is binary compatible with the original class.
I will call the class you want to extend PrivateConstructorClass in the following section.
Take the source code of PrivateConstructorClass and copy it to a source file. The package and class name must not be changed.
Change the constructors of the PrivateConstructorClass from private to protected.
Re-compile the modified source file of PrivateConstructorClass.
Package the compiled class file into a jar archive. E.g. called "patch.jar"
Create a class that extends the first one and compile it against the class in the patch.jar
Change the jvm's classpath so that the patch.jar is the first entry in the classpath.
Now some example code that let you examine how it works:
Expect the following folder structure
+-- workspace
+- private
+- patch
+- client
Create the PrivateConstructor class in the private folder
public class PrivateConstructor {
private String test;
private PrivateConstructor(String test){
this.test = test;
}
#Override
public String toString() {
return test;
}
}
Open a command prompt in the private folder, compile and package it.
$ javac PrivateConstructor.java
$ jar cvf private.jar PrivateConstructor.class
Now create the patch file in the patch folder:
public class PrivateConstructor {
private String test;
protected PrivateConstructor(String test){
this.test = test;
}
#Override
public String toString() {
return test;
}
}
Compile and package it
$ javac PrivateConstructor.java
$ jar cvf patch.jar PrivateConstructor.class
Now comes the interresting part.
Create a class that extends the PrivateConstructor in the client folder.
public class ExtendedPrivateConstructor extends PrivateConstructor {
public ExtendedPrivateConstructor(String test){
super(test);
}
}
and a main class to test it
public class Main {
public static void main(String str[]) {
PrivateConstructor privateConstructor = new ExtendedPrivateConstructor("Gotcha");
System.out.println(privateConstructor);
}
}
Now compile the client folder's source files against the patch.jar
$ javac -cp ..\patch\patch.jar ExtendedPrivateConstructor.java Main.java
and now run it with both jars on the classpath and see what happens.
If the patch.jar comes before the private.jar than the PrivateConstructor class is loaded from the patch.jar, because the application class loader is a URLClassLoader.
$ java -cp .;..\patch\patch.jar;..\private\private.jar Main // This works
$ java -cp .;..\private\private.jar;..\patch\patch.jar Main // This will fail
The solution by #René Link was good enough, but not in my case: I wrote I'm hacking an Eclipse IDE plugin, and this means we're working under OSGi, and this means we cannot control the classpath resolving order (it will load our "hacked" class in our bundle, and vanilla victim class in another bundle, and it will do this with different classloaders, and then we would have problems with casting such objects one to another). Possibly OSGi has some tools to solve this problems, but I don't know it well enough, and also I found no info on this.
So we invented another solution. It is worse than previous one, but at least it works in our case (and so it's more flexible).
The solution is simple: javaagent. It's a standard tool, which allows to manipulate bytecode at the time it is loaded. So the task was solved by using it and java ASM library: the victim's bytecode was modified to make it's constructor public, the remaining was easy.
public class MyAgent {
public static void premain(String agentArguments, Instrumentation instrumentation) {
instrumentation.addTransformer(new ClassFileTransformer() {
#Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException {
if (className.equals("org/victim/PrivateClass")) { //name of class you want to modify
try {
ClassReader cr = new ClassReader(classfileBuffer);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);
for (Object methodInst : cn.methods) {
MethodNode method = (MethodNode) methodInst;
if (method.name.equals("<init>") && method.desc.equals("()V")) { //we get constructor with no arguments, you can filter whatever you want
method.access &= ~Opcodes.ACC_PRIVATE;
method.access |= Opcodes.ACC_PUBLIC; //removed "private" flag, set "public" flag
}
}
ClassWriter result = new ClassWriter(0);
cn.accept(result);
return result.toByteArray();
} catch (Throwable e) {
return null; //or you can somehow log failure here
}
}
return null;
}
});
}
}
Next this javaagent must be activated with JVM flag, and then everything just works: now you can have subclasses which can call super() constructor without any problem. Or this can blow your whole leg off.
EDIT: This clearly doesn't work with the newly posted code examples edited into the question above, but I will keep the answer here for future posterity should it help someone else.
One method available to you which may or may not work depending on your situation is to use the Delegation pattern. For example:
public class PrivateClass {
private PrivateClass instance = new PrivateClass();
private PrivateClass() {/*You can't subclass me!*/
public static PrivateClass getInstance() { return instance; }
public void doSomething() {}
}
public class WrapperClass {
private PrivateClass privateInstance = PrivateClass.getInstance();
public void doSomething() {
//your additional logic here
privateInstance.doSomething();
}
}
You now have a class, WrapperClass, which has the same API as PrivateClass but delegates all the functionality to PrivateClass (after doing some pre or post work itself). Obviously, WrapperClass is not associated with the type heirarchy of PrivateClass but can be setup to do everything PrivateClass can.
I have a situation where Guice is working for some bindings, and not at all for others. Clearly I am using the API incorrectly.
In part, it's probably because I'm trying to get too "fancy" with how I'm using Guice. I've created an inheritance tree of Modules and I think I've gotten too clever (or foolish!) for my own good.
Before you look at the code below, just please understand my intention, which was to provide a reusable Module that I can place in a JAR and share across multiple projects. This abstract, reusable Module would provide so-called "default bindings" that any implementing Module would automatically honor. Things like an AOP MethodInterceptor called Profiler, which looks for methods annotated with #Calibrated and automatically logs how long it took for that method to execute, etc.
Observe the following:
#Target({ ElementType.METHOD })
#RetentionPolicy(RetentionPolicy.RUNTIME)
#BindingAnnotation
public #interface Calibrated{}
public class Profiler implement MethodInterceptor {
#Override
public Object invoke(MethodInvocation arg0) throws Throwable {
// Eventually it will calculate and log the amount of time
// it takes an intercepted method to execute, hence "Profiler".
System.out.println("Intercepted!");
return arg0.proceed();
}
}
public abstract class BaseModule implements Module {
private Binder binder;
public BaseModule() {
super();
}
public abstract void bindDependencies();
#Override
public void configure(Binder bind) {
// Save the binder Guice passes so our subclasses can reuse it.
setBinder(bind);
// TODO: For now do nothing, down the road add some
// "default bindings" here.
// Now let subclasses define their own bindings.
bindDependencies();
}
// getter and setter for "binder" field
// ...
}
public abstract class AbstractAppModule extends BaseModule {
/* Guice Injector. */
private Injector injector;
// Some other fields (unimportant for this code snippet)
public AbstractAppModule() {
super();
}
// getters and setters for all fields
// ...
public Object inject(Class<?> classKey) {
if(injector == null)
injector = Guice.createInjector(this);
return injector.getInstance(classKey);
}
}
So, to use this small library:
public class DummyObj {
private int nonsenseInteger = -1;
// getter & setter for nonsenseInteger
#Calibrated
public void shouldBeIntercepted() {
System.out.println("I have been intercepted.");
}
}
public class MyAppModule extends AbstractAppModule {
private Profiler profiler;
// getter and setter for profiler
#Override
public void bindDependencies() {
DummyObj dummy = new DummyObj();
dummy.setNonsenseInteger(29);
// When asked for a DummyObj.class, return this instance.
getBinder().bind(DummyObj.class).toInstance(dummy);
// When a method is #Calibrated, intercept it with the given profiler.
getBinder().bindInterceptor(Matchers.any(),
Matchers.annotatedWith(Calibrated.class),
profiler);
}
}
public class TestGuice {
public static void main(String[] args) {
Profiler profiler = new Profiler();
MyAppModule mod = new MyAppModule();
mod.setProfiler(profiler);
// Should return the bounded instance.
DummyObj dummy = (DummyObj.class)mod.inject(DummyObj.class);
// Should be intercepted...
dummy.shouldBeIntercepted();
System.out.println(dummy.getNonsenseInteger());
}
}
This is a lot of code so I may have introduced a few typos when keying it all in, but I assure you this code compiles and throws no exceptions when ran.
Here's what happens:
The #Calibrated shouldBeIntercepted() method is not intercepted; but...
The console output shows the dummy's nonsense integer as...29!!!!
So, regardless of how poor a design you may think this is, you can't argue that Guice is indeed working for 1 binding (the instance binding), but not the AOP method interception.
If the instance binding wasn't working, then I would happily revisit my design. But something else is going on here. I'm wondering if my inheritance tree is throwing the Binder off somehow?
And I've verified that I am binding the interceptor to the annotation correctly: I created another package where I just implement Module (instead of this inheritance tree) and use the same annotation, the same Profiler, and it works perfectly fine.
I've used Injector.getAllBindings() to print out the map of all my MyAppModule's bindings as Strings. Nothing is cropping up as the clear source of this bug.
Interception only works on Objects created by Guice (see "Limitations" http://code.google.com/p/google-guice/wiki/AOP#Limitations). You are using "new" to create the DummyObj, so no matter how clever your Module is Set up, the instance is created Outside guice.
Here's a little snipplet based on your coding. (I use your Calibrated Annotation, but had everything else in one class. You should have a look at "AbstractModule". It saves a lot of manual stuff you did with your Module-Hierarchy.
public class MyModule extends AbstractModule implements MethodInterceptor {
#Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("Intercepted#invoke!");
return methodInvocation.proceed();
}
#Override
protected void configure() {
bind(Integer.class).annotatedWith(Names.named("nonsense")).toInstance(29);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(Calibrated.class), this);
}
public static void main(String... args) {
Dummy dummy = Guice.createInjector(new MyModule()).getInstance(Dummy.class);
dummy.doSomething();
System.out.println(dummy.getNonsense());
}
}
And my Dummy:
public class Dummy {
#Inject
#Named("nonsense")
private int nonsense;
public int getNonsense() {
return nonsense;
}
public void setNonsense(int nonsense) {
this.nonsense = nonsense;
}
#Calibrated
public void doSomething() {
System.out.println("I have been intercepted!");
}
}
So you see? I never use the word "new" (except for the Module ....). I let Guice handle the Dummy-Object and just configure the value for the nonsense int, which is then injected.
Output:
Intercepted#invoke!
I have been intercepted!
29
Example:
public class TestClass {
public static void main(String[] args) {
TestClass t = new TestClass();
}
private static void testMethod() {
abstract class TestMethod {
int a;
int b;
int c;
abstract void implementMe();
}
class DummyClass extends TestMethod {
void implementMe() {}
}
DummyClass dummy = new DummyClass();
}
}
I found out that the above piece of code is perfectly legal in Java. I have the following questions.
What is the use of ever having a class definition inside a method?
Will a class file be generated for DummyClass
It's hard for me to imagine this concept in an Object Oriented manner. Having a class definition inside a behavior. Probably can someone tell me with equivalent real world examples.
Abstract classes inside a method sounds a bit crazy to me. But no interfaces allowed. Is there any reason behind this?
This is called a local class.
2 is the easy one: yes, a class file will be generated.
1 and 3 are kind of the same question. You would use a local class where you never need to instantiate one or know about implementation details anywhere but in one method.
A typical use would be to create a throw-away implementation of some interface. For example you'll often see something like this:
//within some method
taskExecutor.execute( new Runnable() {
public void run() {
classWithMethodToFire.doSomething( parameter );
}
});
If you needed to create a bunch of these and do something with them, you might change this to
//within some method
class myFirstRunnableClass implements Runnable {
public void run() {
classWithMethodToFire.doSomething( parameter );
}
}
class mySecondRunnableClass implements Runnable {
public void run() {
classWithMethodToFire.doSomethingElse( parameter );
}
}
taskExecutor.execute(new myFirstRunnableClass());
taskExecutor.execute(new mySecondRunnableClass());
Regarding interfaces: I'm not sure if there's a technical issue that makes locally-defined interfaces a problem for the compiler, but even if there isn't, they wouldn't add any value. If a local class that implements a local interface were used outside the method, the interface would be meaningless. And if a local class was only going to be used inside the method, both the interface and the class would be implemented within that method, so the interface definition would be redundant.
Those are called local classes. You can find a detailed explanation and an example here. The example returns a specific implementation which we doesn't need to know about outside the method.
The class can't be seen (i.e. instantiated, its methods accessed without Reflection) from outside the method. Also, it can access the local variables defined in testMethod(), but before the class definition.
I actually thought: "No such file will be written." until I just tried it: Oh yes, such a file is created! It will be called something like A$1B.class, where A is the outer class, and B is the local class.
Especially for callback functions (event handlers in GUIs, like onClick() when a Button is clicked etc.), it's quite usual to use "anonymous classes" - first of all because you can end up with a lot of them. But sometimes anonymous classes aren't good enough - especially, you can't define a constructor on them. In these cases, these method local classes can be a good alternative.
The real purpose of this is to allow us to create classes inline in function calls to console those of us who like to pretend that we're writing in a functional language ;)
The only case when you would like to have a full blown function inner class vs anonymous class ( a.k.a. Java closure ) is when the following conditions are met
you need to supply an interface or abstract class implementation
you want to use some final parameters defined in calling function
you need to record some state of execution of the interface call.
E.g. somebody wants a Runnable and you want to record when the execution has started and ended.
With anonymous class it is not possible to do, with inner class you can do this.
Here is an example do demonstrate my point
private static void testMethod (
final Object param1,
final Object param2
)
{
class RunnableWithStartAndEnd extends Runnable{
Date start;
Date end;
public void run () {
start = new Date( );
try
{
evalParam1( param1 );
evalParam2( param2 );
...
}
finally
{
end = new Date( );
}
}
}
final RunnableWithStartAndEnd runnable = new RunnableWithStartAndEnd( );
final Thread thread = new Thread( runnable );
thread.start( );
thread.join( );
System.out.println( runnable.start );
System.out.println( runnable.end );
}
Before using this pattern though, please evaluate if plain old top-level class, or inner class, or static inner class are better alternatives.
The main reason to define inner classes (within a method or a class) is to deal with accessibility of members and variables of the enclosing class and method.
An inner class can look up private data members and operate on them. If within a method it can deal with final local variable as well.
Having inner classes does help in making sure this class is not accessible to outside world. This holds true especially for cases of UI programming in GWT or GXT etc where JS generating code is written in java and behavior for each button or event has to be defined by creating anonymous classes
I've came across a good example in the Spring. The framework is using concept of local class definitions inside of the method to deal with various database operations in a uniform way.
Assume you have a code like this:
JdbcTemplate jdbcOperations = new JdbcTemplate(this.myDataSource);
jdbcOperations.execute("call my_stored_procedure()")
jdbcOperations.query(queryToRun, new MyCustomRowMapper(), withInputParams);
jdbcOperations.update(queryToRun, withInputParams);
Let's first look at the implementation of the execute():
#Override
public void execute(final String sql) throws DataAccessException {
if (logger.isDebugEnabled()) {
logger.debug("Executing SQL statement [" + sql + "]");
}
/**
* Callback to execute the statement.
(can access method local state like sql input parameter)
*/
class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider {
#Override
#Nullable
public Object doInStatement(Statement stmt) throws SQLException {
stmt.execute(sql);
return null;
}
#Override
public String getSql() {
return sql;
}
}
//transforms method input into a functional Object
execute(new ExecuteStatementCallback());
}
Please note the last line. Spring does this exact "trick" for the rest of the methods as well:
//uses local class QueryStatementCallback implements StatementCallback<T>, SqlProvider
jdbcOperations.query(...)
//uses local class UpdateStatementCallback implements StatementCallback<Integer>, SqlProvider
jdbcOperations.update(...)
The "trick" with local classes allows the framework to deal with all of those scenarios in a single method which accept those classes via StatementCallback interface.
This single method acts as a bridge between actions (execute, update) and common operations around them (e.g execution, connection management, error translation and dbms console output)
public <T> T execute(StatementCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(obtainDataSource());
Statement stmt = null;
try {
stmt = con.createStatement();
applyStatementSettings(stmt);
//
T result = action.doInStatement(stmt);
handleWarnings(stmt);
return result;
}
catch (SQLException ex) {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
String sql = getSql(action);
JdbcUtils.closeStatement(stmt);
stmt = null;
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw translateException("StatementCallback", sql, ex);
}
finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
Everything is clear here but I wanted to place another example of reasonable use case for this definition type of class for the next readers.
Regarding #jacob-mattison 's answer, If we assume we have some common actions in these throw-away implementations of the interface, So, it's better to write it once but keep the implementations anonymous too:
//within some method
abstract class myRunnableClass implements Runnable {
protected abstract void DO_AN_SPECIFIC_JOB();
public void run() {
someCommonCode();
//...
DO_AN_SPECIFIC_JOB();
//..
anotherCommonCode();
}
}
Then it's easy to use this defined class and just implement the specific task separately:
taskExecutor.execute(new myRunnableClass() {
protected void DO_AN_SPECIFIC_JOB() {
// Do something
}
});
taskExecutor.execute(new myRunnableClass() {
protected void DO_AN_SPECIFIC_JOB() {
// Do another thing
}
});