Using the NetBeans Platform on the Server with Wicket on the Client
Now, let's have a look at the NetBeansPlatformUtils class. First, the method to install the Platform class loader:
private final static URL[] NO_URLS = new URL[0];
public static ClassLoader installPlatformClassLoader()
{
final ClassLoader classLoaderSave = new URLClassLoader(NO_URLS, Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(Lookup.getDefault().lookup(ClassLoader.class));
return classLoaderSave;
}
The only note worth mentioning is that the Platform class loader is wrapped by a URLClassLoader: I've experienced some ClassCastExceptions by the JSP facility of Tomcat, that expects the relevant class loader to be URL - based. While I'm not interested in JSPs (and I noted that the exceptions were harmless for my application), the less obscure exceptions at runtime, the better.
Then, the boot() method, which just mimics the needed initialization parts performed by the NetBeans launcher:
private static volatile boolean initialized;
public synchronized static void boot (final ServletContext servletContext)
throws Exception
{
if (!initialized)
{
initialized = true;
final String fallbackNetBeansHome = servletContext.getInitParameter("netBeansHome");
final String fallbackNetBeansUser = servletContext.getInitParameter("netBeansUserDir");
final String netBeansHome = resolveProperties(System.getProperty("netbeans.home", fallbackNetBeansHome));
final String netBeansUser = resolveProperties(System.getProperty("netbeans.user", fallbackNetBeansUser));
final String netBeansDirs = findClusters(netBeansHome);
System.setProperty("netbeans.osenv.nullsep", "false");
System.setProperty("netbeans.home", netBeansHome);
System.setProperty("netbeans.dirs", netBeansDirs);
System.setProperty("netbeans.logger.console", "true");
System.setProperty("netbeans.user", netBeansUser);
new File(netBeansHome + "/config").mkdirs();
new File(netBeansUser).getParentFile().mkdirs();
org.netbeans.Main.main(new String[] { "--nosplash", "--userdir", netBeansUser });
}
Worth mentioning is the "--nosplash" argument, that prevents the pop up window showing the initialization process from appearing at startup. The "netbeans.dirs" property must point to all the directories where a cluster (a set of related modules) has been prepared; you could statically configure this property with a property file, while I prefer to have it discovered at runtime (it's a matter of taste - I preferred this approach for blueMarine too, which has got a custom launcher):
private static String findClusters (final String netBeansHome)
throws IOException
{
final StringBuilder clusters = new StringBuilder();
final File[] files = new File(netBeansHome).listFiles();
if (files == null)
{
throw new IllegalArgumentException("Platform directory empty: " + netBeansHome);
}
for (final File file : files)
{
if (file.isDirectory())
{
final File updateTrackingFolder = new File(file, "update_tracking");
if (updateTrackingFolder.exists())
{
// platform* is already added as the main directory
// if (!file.getName().startsWith("platform"))
{
if (clusters.length() > 0)
{
clusters.append(File.pathSeparator);
}
clusters.append(file.getCanonicalPath());
}
}
}
}
final String buildDir = System.getProperty("netbeans.build.dir");
if (buildDir != null)
{
clusters.append(File.pathSeparator);
clusters.append(buildDir);
}
return clusters.toString();
}
The boot code also needs to know about two directories, specified as parameters:
- "netBeansHome": where the Platform runtime is installed (root of all clusters)
- "netBeansUserDir": where the Platform configuration files will be placed (and, eventually, the application ones too).
For convenience, I've implemented a simple macro-substitution facility for system properties - you'll see later that this is pretty useful for facilitating both development and deployment:
private static String resolveProperties (final String string)
{
String result = string;
for (final Entry<Object, Object> entry : System.getProperties().entrySet())
{
final String propertyName = (String)entry.getKey();
final String propertyValue = (String)entry.getValue();
result = result.replace("{" + propertyName +"}", propertyValue);
}
return result;
}
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)






Comments
Harris Goldstone replied on Fri, 2009/01/09 - 3:25pm
Fabrizio Giudici replied on Sun, 2009/01/11 - 7:12am
Hi Harris.
At the moment, the great advantage is for what concerns the tier of services and models, that is the business tier. It is something that can be best clarified by examples, and I'll post some in future here on DZone (also with other two "series" of posts about NetBeans Platform Idioms etc...); for the moment, take this small one: I have a Metadata infrastructure that allow to extract metadata from media (e.g. photos), eventually store them in a database, where they can be searched for. Every kind of metadata (EXIF, IPTC, whatever) is implemented by separate modules, as well as persistence in the database is enabled by just adding specific modules, without requiring any configuration. This means that I can easily satisfy different needs (blueMarine itself, blueOcean base, blueOcean as used by my customer, and hopefully other future customers) by just assembling different set of modules in specific custom platforms. This has been achieved mostly by means of the Lookup API (and in future I could use more the layer.xml facility). Most of this stuff could be used also by taking simple .jars as libraries out of the NetBeans Platform; but as the number of configurations increases, it is really important to have the capability of checking compatibilities and dependencies among modules. You could be always safe with a good testing, but in any case I appreciate when a static tool finds / prevents problems as early as possible. Furthermore, having the very same process for two different projects is a big time saver for me.
There are two different uses of the Platform that I'll evaluate soon. First is the "Event Bus" (based on "Central Lookup" by Wade Chandler) that I've talked about a few months ago; in blueMarine it introduces another great deal of decoupling that in the customer's project based on blueOcean I don't have yet. While the Event Bus as is works fine with a single user (it is a singleton), it must be adapted in the case of concurrency (it should be enough to write a variant based on ThreadLocal). Second is about the use of Nodes for a number of things, including dynamic generation of menus based on the functions that you have dynamically included in the current configuration. This is more sensible because of the cited potential problem with the AWT Thread, which would be a serious bottleneck on the server side.
Aldo Brucale replied on Mon, 2009/01/19 - 8:49am
org.netbeans.Mainfrom my module? It belongs to the Bootstrap module, but when I add this dependency and try to compile, the build system says that the module containing NetBeansPlatformUtils "is not a friend of<nb-platform-dir>/nbbuild/netbeans/platform9/lib/boot.jar".Fabrizio Giudici replied on Mon, 2009/01/19 - 9:08am
Aldo Brucale replied on Mon, 2009/01/19 - 11:22am
in response to:
Fabrizio Giudici
Thank you Fabrizio, of course a module cannot boot the application that is supposed to load it!
I placed the servlet in a regular web project, now it works perfectly. Very interesting, thank you.
Matthew Dempesy replied on Sat, 2011/01/08 - 9:30pm
Matt Coleman replied on Thu, 2013/02/21 - 1:09am
in response to:
Fabrizio Giudici
thanks for explaining this issue Fabrizio..I now understand why
buffalo freelance web designer