public SomeClass extends LookupListenerIf you still have problems, then check the META-INF/services folder of your implementation, there is probably a typo in the flat file. Its better to use @Service annotation to avoid such mistakes.
{
//It is important that you hold a reference to Lookup.Result
//so that it doesn't get garbage collected. This also applies to Lookup.Template
private Lookup.Result result = lookup.getDefault().lookupResult(MyInterface.class);
public SomeClass()
{
result.addLookupListener(this);
//It is important to call this method once...otherwise
//resultChanged(...) method is never triggered!!
resultchanged(new LookupEvent(result));
}
public void resultChanged(LookupEvent ev)
{
//do your stuff here...
}
}
Sunday, June 14, 2009
LookupListener problem?
Plugin manager for standalone swing apps
Lookup API provides amazing decoupling capabilities to your application, even in standalone and non visual applications. The problem comes when you have to install or remove modules from your applications (implementations of an interface). In Netbeans platform the plugin manager would automatically do this for you. To utilize the benefits of LookupListener, one has to add the module jar files to the classpath (at run time).
This however cannot be achieved directly, here's a reflection hack to get it done:
/**In the above code we are adding a URL (typically pointing to a jar file) to the system classloader by invoking its private method via reflection.
* Rescans the given folder and adds all the Jar files (plugins)
* to class path...simply ignores if a jar file is already added...
*
* @param path The folder containing plugins...
* @throws java.io.IOException
*/
public void rescan(String path) throws IOException
{
File pluginFolder = new File(path);
File plugins[] = pluginFolder.listFiles(new FileFilter()
{
public boolean accept(File pathname)
{
if(pathname.getPath().endsWith(".jar"))
return true;
else
return false;
}
});
for(File f : plugins)
{
addPlugin(f.toURI().toURL());
}
}
/**
* The url (preferably jar) to be added to the classpath.
* This is like an install plugin thingy...
* Must be used in place of {@link #rescan(java.lang.String) rescan} method
* if a single new plugin is to be installed...gives good performance ups
*
* @param url The url to be added to classpath
*/
public void addPlugin(URL url) throws IOException
{
addURLToClassPath(url);
}
/**
* To avoid un-necessary object creation on method calls...
*/
private static final Class[] parameters = new Class[]{URL.class};
/**
* Adds a URL, preferably a JAR file to classpath. If URL already exists,
* then this method simply returns...
*
* @param u The URL t be added to classpath
* @throws java.io.IOException
*/
private void addURLToClassPath(URL u) throws IOException
{
URLClassLoader sysloader = URLClassLoader)ClassLoader.getSystemClassLoader();
boolean isAdded = false;
for(URL url : sysloader.getURLs())
{
if(url.equals(u))
isAdded = true;
}
if(isAdded)
return;
Class sysclass = URLClassLoader.class;
try
{
Method method = sysclass.getDeclaredMethod("addURL",parameters);
method.setAccessible(true);
method.invoke(sysloader, new Object[]{ u });
}
catch (Throwable t)
{
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
}
}
In your plugin manager...all you have to do is paste the jar file to a certain folder (say user.dir/plugins), then execute the following code to add jars to classpath:
That's it! the newly registered service providers can be caught in resultChanged(...) method of the LookupListener. Similarly you can remove items from the classpath to deactivate the plugins from your application, i'll leave that as your home work assignment :)
/**
* Rescans the given folder and adds all the Jar files (plugins)
* to class path...simply ignores if a jar file is already added...
*
* @param path The folder containing plugins...
* @throws java.io.IOException
*/
public void rescan(String path) throws IOException
{
File pluginFolder = new File(path);
File plugins[] = pluginFolder.listFiles(new FileFilter()
{
public boolean accept(File pathname)
{
if(pathname.getPath().endsWith(".jar"))
return true;
else
return false;
}
});
for(File f : plugins)
{
addPlugin(f.toURI().toURL());
}
}
/**
* The url (preferably jar) to be added to the classpath.
* This is like an install plugin thingy...
* Must be used in place of {@link #rescan(java.lang.String) rescan} method
* if a single new plugin is to be installed...gives good performance ups
*
* @param url The url to be added to classpath
*/
public void addPlugin(URL url) throws IOException
{
addURLToClassPath(url);
}
Wednesday, June 10, 2009
lookup third party service impl of an interface
1) Use library wrapper wizard in Netbeans to create a jar module wrapper.
2) Create a folder META-INF/services in the wrapper module.
3) Create a file in META-INF/services named after the fully qualified name of the interface containing the fully qualified names of the implementations (one per line)
That's it!
Third party service implementations to now be discovered by the global lookup on startup.
Sunday, June 7, 2009
Unnecessary object creation...
I had this situation:
loopWhen i ran the profiler. I noticed that the major portion of CPU was going into Double object creation. That's when i realized that its the classloader overload everytime the object is being created..so this is what i did:
{
Double d = someclass.compute();
}
//init variable...This simple optimization reduced a lot of CPU overload! Also if u have situations such as:
Double d = 0.0;
loop
{
d = someclass.compute();
}
loopIf feasible...try using:
{
Obj o = new Obj();
}
Obj o = new Obj();This approach is not always feasible...especially if you intend to use the reference of the object elsewhere, my point is, to reduce object creation wherever feasible.
loop
{
//use o...
o.set(abc);
}
Wednesday, May 27, 2009
My ideal desktop recipe
- Validation
- Binding Pojo's with GUI
- Database Management
- Cool and sleek GUI
- Code complexity
- Packaging and deployment
- Creating Trialware's
1) Validation
I never paid much attention initially, but validation is one aspect that tends to get laborious. There are popular validation frameworks out there to help you with it. But as a beginner you'll want to learn it quick and easy. I'd prefer the Simple Validation Api by Tim Boudreau. Powerful and simple at the same time. Hardly takes 10 minutes to learn.
2) Binding POJO's with GUI
In my opinion there is no good tool for data binding, its currently unstable and there's no out of the box support for it. Its usually more pain than gain. But if u insist i suggest that you use the Netbeans IDE, it features mattise GUI builder with binding support. It'd be nice if JComponent binds POJO via annotations. In either case be on a look out, some one is probably developing it right now.
3) Database Management
Would'nt it be nice if you didnt have to write all the plumbing code required to execute a database transaction and just concentrate on the task itself? ORM's typically sheild you from all the database junk. Hibernate will probably be the first result if u ever tried to google. It however has a lot of XML mapping stuff to be done.
In my opinion, ActiveObjects orm by Daniel Spiewak is the easiest to use, i.e., in case u dont have distributed databases to deal with. It conpletely sheilds you from database complexity. The only disadvantage is that u need to create POJO interfaces first to generate the database schema . If you already have a database then you must create the interfaces yourself (no generator tool for now). A great feature worth noting is that it has Database Migrations (useful for maintenance).
4) Cool and sleek GUI
Get substance look and feel by Kirill Grouchnikov is an excellent option to spice up you UI. All you have to do is add one line of code. If you're on MAC OS consider Quaqua lnf. Also check out SwingX, Flamingo, L2fProd, JGoodies for cool swing components.
If you have time to spare and want some extreme GUI with cool animation effects consider using Animated Transitions Api and Timing Framework by Romain Guy and Chet Haase. I also suggest that you read Filthy Rich clients by the same authors.For a quickie, with almost no learning curve u should use substance look and feel with SwingX components along with mattise in NetbeansIDE.
5) Code Complexity
Be it a small or a large project, a GUI application soon gets out of the hand or you'll find yourself handling messy code or writing lots of plumbing code instead of putting effort into the business logic of the application. There's no point in reinventing the wheel, its always better to reuse a well tested framework instead of making one on your own.
For a small scale application its better to use to use your own MVC pattern to separate model, view and control. Major concerns in such application would be to maintain configuration. You'll probably use bean property change listeners...in this case consider using AbstractSerializableBean from swingX project to reduce the amount of boilerplate code for firing property change. It your application still gets out of hand consider using JIDE Application framework...havent really tried it, but looks good and has a moderate learning curve (2-3 days)For a large application it is best of you use Netbeans Platform, its pretty complex and has a high learning curve, i would'nt recommend it unless you want to reuse netbeans features such as pallete, property sheets and editors etc...but on the bottom line its got great support and excellent documentation. Since its developed by sun, you can expect great support. Moreover NetbeansIDE has lots of code completion features for leveraging a netbeans platform based application.
If you have at least made 5-6 desktop applications and have good knowledge of OOPS, especially the use of interfaces and abstract classes (read this post for information on abstract classes) then you must consider using the Netbeans platform. Start by viewing these excellent screencasts.
6) Packaging and deployment
Consider an application based on java comm api. In such an app, you cant ask your client to copy and paste dll's at different locations, this should instead be done automatically at the deployment time, typically by distributing a setup file. To encash the benefits of cross platform nature of your java code, you'll need to use a cross platform deployer. Again, there are many of them, the easiest one to use and learn is by using PackJacket, a GUI frontend to the IzPack project. It also lets you create runtime scripts to execute custom tasks. whats more, the project is open sourced and is free to use.
7) Creating Trialwares
Depending on your marketing strategy, you might want to create trialware applications that expire after a certain time period.I recommend using TrueLicense library. Will take 1 day to get a hang of it.
Hope the above collection of tools and libs help you be more productive... Please let me know if you find better and easier tools.