I have what seems like a tricky Java library task.
I need to write an adapter/helper class for working with JTable
s that has some additional functionality if the JTable
is a JXTable
. But I don't want to add a runtime dependency on swingx-core-1.6.2.jar unless my application actually uses JXTable (in which case it already requires having the SwingX jar file on the classpath)
How can I decouple my code to accomplish this? I don't even know how I can test for JXTable; if I try to use instanceof JXTable
as a test, that means my code already has an unconditional runtime dependency on JXTable.
I have written Java libraries before that have "optional" runtime linkage dependencies: if I have this in my library:
package com.foobar.foolib;
// import from whizbang.jar
import com.whizbang.BloatwareThingy;
public class SuperObject
{
/* ... uses a BloatwareThingy ... */
}
and SuperObject
is the only class that uses whizbang.jar, then as long as my end application doesn't use SuperObject
, then there's no runtime dependency on whizbang.jar; if my end application does want to use SuperObject
, then it needs to include whizbang.jar on the classpath. Optional from the standpoint of the application. Works great.
How can I write a method to test for a given JTable being an instance of JXTable, without requiring a dependency on the SwingX jar file if the application only uses JTable?
You can test with:
Class cls = null;
try {
cls = Class.forName( "org.jdesktop.swingx.JXTable" );
} catch( Throwable ex ) {}
if( cls != null )
// have JXTable
After that you would have to use Reflection exclusively for all accesses to classes, methods, constructors and fields from that external library.
As this can become very clumsy if you need to access a large API this way you could write helper classes that can use JXTable directly but get created via Reflection and invoked via interfaces or abstract classes:
public interface MyTableHandler
{
void doSomethingWithTable( JTable table );
}
public class JXTableHandler implements MyTableHandler
{
void doSomethingWithTable( JTable table )
{
JXTable jxt = (JXTable) table;
// use JXTable API directly ...
}
}
public class StdTableHandler implements MyTableHandler
{
void doSomethingWithTable( JTable table )
{
// do without JXTable
}
}
public class MyIndependentClass
{
static final MyTableHandler handler;
static {
try {
Class.forName( "org.jdesktop.swingx.JXTable" ); // force exception
handler = (MyTableHandler) Class.forName( "my.pkg.JXTableHelper" )
.newInstance();
} catch( Throwable ex ) {
handler = new StdTableHandler();
}
}
public void treatTable( JTable table )
{
handler.doSomethingWithTable( table );
}
}
The Java VM has no problems with the usage of nonexisting API in classes that are not used themselves but are only present in jar files. With this approach you would use JXTableHandler only if org.jdesktop.swingx.JXTable is available and StdTableHandler otherwise.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With