Using the Java Plugin Framework in a web application
I had quite a lot of trouble trying to figure this out properly. The JPF web site only gives examples of how to integrate the framework into a desktop application and I couldn't really figure out how to integrate it into a web application. The forums on the project are also almost dead and so there is little help available but it is still the only alternative for a plugin framework other than the OSGI, which looked overly complicated for what I needed. This is the full code that I needed. I will explain each part later on:
ExtendedProperties extendedProperties = new ExtendedProperties(new Properties());
ShadingPathResolver shadingPathResolver = new ShadingPathResolver(prosocPluginShadowFolderLocation);
extendedProperties.put("org.java.plugin.PathResolver", shadingPathResolver);
extendedProperties.put("unpackMode", "always");
PluginRegistry pluginRegistry = new PluginRegistryImpl();
pluginRegistry.configure(extendedProperties.getSubset("org.java.plugin.registry.xml.PluginRegistryImpl" + "."));
try {
shadingPathResolver.configure(extendedProperties); // no point in calling this as the method is empty
} catch (Exception e) {
logger.error("Exception setting extendedProperties on shadingPathResolver [" + e + "]");
}
jpfPluginManager = ObjectFactory.newInstance().createManager(pluginRegistry, shadingPathResolver);
// Get the directory where the plugins are located
File filePluginDirectory = new File(pluginDirectory);
// Get all the files with the correct extension
File[] pluginFiles = filePluginDirectory.listFiles(new FilenameFilter() {
public boolean accept(File directory, String name) {
// Add the plugins to the File[]
return name.toLowerCase().endsWith(prosocPluginFileExtension);
}
});
// If we have some plugins then publish them
String thisPluginLocation;
PluginLocation[] pluginLocations = new PluginLocation[pluginFiles.length];
for (int i = 0; i < pluginFiles.length; i++) {
try {
// Create the plugins
pluginLocations[i] = StandardPluginLocation.create(pluginFiles[i]);
} catch (MalformedURLException murle) {
logger.error("Could not add plugin to pluginLocations [" + murle + "]");
}
}
try {
getJPFPluginManager().publishPlugins(pluginLocations);
} catch (JpfException jpfe) {
throw new RuntimeException("Error publishing plugins: ", jpfe);
}
The first section is:
ExtendedProperties extendedProperties = new ExtendedProperties(new Properties());
ShadingPathResolver shadingPathResolver = new ShadingPathResolver(prosocPluginShadowFolderLocation);
extendedProperties.put("org.java.plugin.PathResolver", shadingPathResolver);
extendedProperties.put("unpackMode", "always");
This creates a ShadingPathResolver and adds it to a special JPF properties file of type ExtendedProperties. The unpack mode is set to always unpack the plugin to a shadowFolder and the location of that shadowFolder is defined in a file called jpf.properties.
String folder = shadowFolderLocation; // was originally config.getProperty("shadowFolder"); in jpf.jar
jpf.properties contains:
shawowFolder=/WEB-INF/.plugin
The second section:
PluginRegistry pluginRegistry = new PluginRegistryImpl();
pluginRegistry.configure(extendedProperties.getSubset("org.java.plugin.registry.xml.PluginRegistryImpl" + "."));
try {
shadingPathResolver.configure(extendedProperties); // no point in calling this as the method is empty
} catch (Exception e) {
logger.error("Exception setting extendedProperties on shadingPathResolver [" + e + "]");
}
jpfPluginManager = ObjectFactory.newInstance().createManager(pluginRegistry, shadingPathResolver);
creates and configures a plugin registry. The registry is where the information about the available plugins and whether or not those plugins are active or not, is held. The last line then creates us a PluginManager using the PluginRegistry and the ShadingPathResolver that we created earlier. The next part of the code:
// Get the directory where the plugins are located
File filePluginDirectory = new File(pluginDirectory);
// Get all the files with the correct extension
File[] pluginFiles = filePluginDirectory.listFiles(new FilenameFilter() {
public boolean accept(File directory, String name) {
// Add the plugins to the File[]
return name.toLowerCase().endsWith(prosocPluginFileExtension);
}
});
scans the folder pluginDirectory which in my case is /WEB-INF/plugin creates an array of type File of any files in the folder that have a .zip or a .jar extension. These extensions are the default files that the JPF will consider to be a plugin. The second to final part is:
// If we have some plugins then publish them
String thisPluginLocation;
PluginLocation[] pluginLocations = new PluginLocation[pluginFiles.length];
for (int i = 0; i < pluginFiles.length; i++) {
try {
// Create the plugins
pluginLocations[i] = StandardPluginLocation.create(pluginFiles[i]);
} catch (MalformedURLException murle) {
logger.error("Could not add plugin to pluginLocations [" + murle + "]");
}
}
This simply loops through our File[] and turns it into something that the JPF can understand. In this case a PluginLocations[]. Finally we can publish the plugins with the following:
try {
getJPFPluginManager().publishPlugins(pluginLocations);
} catch (JpfException jpfe) {
throw new RuntimeException("Error publishing plugins: ", jpfe);
}
The end result of running this code is to extract the code from the plugin into the folder /WEB-INF/.plugin folder where the JPF can now run that code from. Notice that the actual .zip files are stored in /WEB-INF/plugin but they are extracted to /WEB-INF/.plugin which is where they will be run from.
All thought the framework is currently unsupported and no longer in development I have found it to be excellent. I can reload the plugins without having to either reload the server context or restart the server.
27.02.2009 07:23 - Posted by doahh - Comments: 1 - Java

Comments:
Wow, amazing that you got it working in web.
I was wondering if you can help me to get it working with jsf and icefaces.
I would really appreciate it.
Kind Regards
Cobus Stroebel
25.07.2011 10:12 - Posted by Cobus Stroebel - Permalink