Writing a (bit complex) Glassfish Update Module
There have already been a few blogs on creating Glassfish addon modules and update center modules. In particular, the one by Manveen and Alexis are pretty good, and clear. Please read them first, if you're looking to create an update center module.
That said, they both only cover a small amount of the information you need.
First, let's go over the actual structure of the program - there's really three different parts: The addon module (which has two parts, the installer and the configurator), and the update center module itself. The addon module is the way to actually modify Glassfish, while the update center module is just a delivery mechanism for the addon module. In fact, you can run the addon module without the update center by issuing the command
asadmin install-addon addonfilename.jar, as well as removing the addon with
asadmin uninstall-addon addonname.
The addon module is divided into two parts - the installer, and the configurator. The installer runs when the addon is first run, and it knows about the location of the install directory of the App Server. This is the process that you'd use to actually move all the files around to their proper places. The configurator runs when you next restart the App Server, and it knows about the location of the server instance that it's started under. This is the process that you would use to modify the server's configuration, located in the domain.xml file.
So, with all that in mind, take a look at the code that I wrote, and follow along:
First, we'll write the installer. This class implements com.sun.appserv.addons.Installer, and there are two methods that matter to us right now - install and uninstall. To install, we're going to take two files (jsf-api.jar, and jsf-impl.jar) and put them into the lib directory of Glassfish, backing up the existing jsf-impl.jar. Uninstall will reverse the process. First, we need to find destination directory - we do this by using the InstallationContext we're passed as part of the method call:
File appserverDir = ic.getInstallationDirectory();
String appServerInstallRoot = appserverDir.getAbsolutePath();
String appServerLibDir = appServerInstallRoot + File.separator + "lib";
And we also need to find the source for these files - which is the jar that we created for the install.
String addOnsDir = appServerInstallRoot + File.separator + "addons";
String installerJar =
addOnsDir + File.separator + INSTALLER_JAR;
Where INSTALLER_JAR is the name of the installer file.
Now, the rest of the program is just standard unjar, copy, and move commands in Java, except for one last thing: we also need to place the configurator jar someplace where the starting App Server instance will find it upon next startup.
String addOnsLibDir = appServerInstallRoot + File.separator+ "lib" + File.separator + "addons";
File confJarFrom = new File(tmpWorkDir + File.separator + CONFIGURATOR_JAR);
File confJarTo = new File(addOnsLibDir + File.separator + CONFIGURATOR_JAR);
Where, once again, CONFIGURATOR_JAR is the name of the jar file that holds the configurator information.
Now we'll talk about the configurator. Don't worry, we'll discuss packaging next. The configurator implements com.sun.appserv.addons.Configurator, and once again, there are two methods we need to be concerned about: configure and unconfigure. Our configure method does only one thing: it loads the domain.xml configuration file into a DOM tree, modifies the part that we need to change, and then writes it back out. Unconfigure will reverse this process. First, we need to find the domain.xml file for the running instance:
String domainRoot = cc.getDomainDirectory().getAbsolutePath();
String domainFilePath = domainRoot
+ File.separator + "config"
+ File.separator + "domain.xml";
File domain = new File(domainFilePath);
Then we simply modify the xml and rewrite it in a fairly standard manner. Note that since we're going to be changing the classpath of the server, a addtional restart is going to be required, for a total of two restarts (one to run the configurator, and one more to change the classpath.)
Now, let's talk packaging, because that's the entirety of what's left to do. Manveen's blog covers this, but it's worth going over again.
The configurator jar will have two parts - a file, called services/com.sun.appserv.addons.Configurator which contains the name of the file implementing Configurator as it's content, and the class files, including the named file. Also, the configurator jar file should be named something like addonname_configurator_versionstring.jar by convention.
The installer jar is similar in structure - a file, named services/com.sun.appserv.addons.Installer containing the name of the file implementing the Installer interface. The installer jar will also have the files to install, such as jsf-impl.jar in our case, as well as the configurator jar file mentioned above. This installer jar is the file that you can use with the asadmin install-addon command.
Lastly, there's the Update Center module jar. The format of this jar is based on the Netbeans module format. Pretty simple stuff - there's two top level directories - info and module. Under module, we have the installer jar file. Under info, we place a small info.xml file, which is basically just a stub. Ours looks like this:
<description>JavaServer Faces 2.0 EDR1 Release</description>
Lastly, if you want to put this into the official Glassfish Update Center, you'll need an additional xml file - for information on this, check out Manveen's Update Center Testing blog.
So, that's it - how to write an update center module that installs a new library, and adds it to the classpath of the app server in domain.xml. Hope this helps you.
UPDATE: There's a little confusion about how uninstalling works, so it's probably worth a quick note: GF v2 doesn't support a programmatic unconfigure (or for that matter, uninstall) via the updatetool - when you want to uninstall an installed module, you need to first manually edit a configuration file called domain-registry in your domain's config directory (the same place as the domain.xml file). You'll find two properties there - change them to "false". My file looks like this:
#Wed Jun 25 13:17:28 PDT 2008
Once you've changed these files, bounce the server. That will run the Configurator's unconfigure method of the configurator class. Then, uninstall the package either via the updatetool or via
asadmin uninstall-addon addonname - that will then run the uninstall method of the installer class.