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...
}
}
Showing posts with label netbeans platform. Show all posts
Showing posts with label netbeans platform. Show all posts
Saturday, June 13, 2009
LookupListener problem?
There are many unanswered threads to this question. The common issue is that the resultChanged(...) method is never triggered!! Here is a proper use-case scenario (note the comments, they provide tips to avoid common loopholes)
Plugin manager for standalone swing apps
Lookup API provides more features than the typical ServiceLoader mechanism introduced in JDK 6. It allows you to listen to changes using LookupListener. If your not aware of Lookup API, please read about it here before continuing any further. For a more comprehensive tutorial on the subject, check out this screencast
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 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:
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
If you have a jar file containing implementations of an interface that you want to be discovered by lookup...here's what you do:
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.
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.
Subscribe to:
Posts (Atom)