FreeMarker in NetBeans IDE 6.0: First Scenario
NetBeans IDE 6.0 provides support for FreeMarker, on many levels, covering a variety of scenarios. To not confuse things, I'll deal with each scenario in a separate article. The first scenario is aimed at NetBeans plugin authors. Authors of plugins frequently need to provide file templates to the users of their plugins. In short, FreeMarker is the language you can use to define these file templates.Your users will not deal with these file templates, at least not necessarily. Instead, they will use a wizard that will generate a file. Under the hood, the wizard will pass the values typed by the user (in the wizard's panels) to a FreeMarker file template for processing. In this article, I will show how you create such a file template and how to hook it into a wizard. In short, you will create a NetBeans module that provides a wizard that passes values to a FreeMarker template to generate a document when the user clicks "Finish" in the wizard.
Take the steps below:
- Install the FreeMarker plugin. Install the FreeMarker Template Sample into NetBeans IDE 6.0. When you do this, you will be providing a sample project that will install syntax coloring and code completion for FreeMarker. (The sample plugin will also install other things, but so as not to confuse things, we won't look at these other features in this article.)
- Get the sample and install it. After you install the above plugin, go to Samples | NetBeans Modules in the New Project wizard (Ctrl-Shift-N). There you will find "FreeMarker Support Sample". Complete the wizard by clicking Next and Finish. Right-click the project node and install it. Now, all files that end in "ftl" or "template" will have FreeMarker syntax coloring and code completion. We will see this in action in a future step below.
- Create the plugin's initial source structure. Create a new module project, choosing NetBeans Modules | Module in the New Project wizard, and then completing the wizard, giving the project any name and code name base you like. In this case, I am interested in creating a module containing file templates for the "ItsNat" web framework. Therefore, I've called the module "ItsNatFileTemplates" and the code name base "org.netbeans.modules.itsnatfiletemplates".
- Generate a wizard. Let's generate the wizard's structure. Right-click the project node and choose New | Other. In the New Project wizard, choose Module Development | Wizard. Click Next. Choose "New File" and type "1" in "Number of Wizard Panels". Click Next. Type something in the class name prefix, such as "ItsNatServlet". Set something appropriate in the Category, Icon, and Package fields. Click Finish. Here's my source structure at this point:
We don't need to know much about the generated code. We'll deal with the files one by one, as we need them. First, we will work with the iterator class, above it is called "ItsNatServletWizardIterator". We are going to modify it in such a way that we will add an existing panel, from the NetBeans sources, to our sequence of panels. Currently, we only have one and it is blank (look at "ItsNatServletVisualPanel1" in Design mode). So, we are going to replace this panel with an existing panel.
The existing panel provides the fields "Class Name", "Project", and "Package", which we therefore will not need to create ourselves. Before continuing, open the layer file and add one attribute below the other attributes (or anywhere in the list) that modify the file template, to specify that we will be making use of the FreeMarker template engine:<attr name="javax.script.ScriptEngine" stringvalue="freemarker"/>
- Set dependencies. In the next steps, we'll be adding code to the wizard iterator. Before doing so, we need to set some dependencies on modules that provide the NetBeans APIs that we will need. Therefore, set dependencies on the following: 'Java Project Support', 'Project API', and 'Project UI API' (right-click the project in the Projects window, choose Properties, click Libraries, then set dependencies on the above three and click OK).
- Specify our wizard panel. The first lines of the "getPanels()" method in the "ItsNatServletWizardIterator" are as follows:
private WizardDescriptor.Panel[] getPanels() {
if (panels == null) {
panels = new WizardDescriptor.Panel[]{
new ItsNatServletWizardPanel1()
};
Replace the above lines with these:private WizardDescriptor.Panel packageChooserPanel;
private WizardDescriptor.Panel[] getPanels() {
Project project = Templates.getProject(wizard);
Sources sources = (Sources)project.getLookup().lookup(Sources.class);
SourceGroup[] groups = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
packageChooserPanel = JavaTemplates.createPackageChooser(project,groups);
if (panels == null) {
panels = new WizardDescriptor.Panel[] {
packageChooserPanel,
}; - Clean up. Fix imports (Ctrl-Shift-I), making sure to select "org.netbeans.spi.project.ui.templates.support.Templates" from the Fix All Imports box. You can now delete the two classes that form the panel. That is, just delete the wizard panel and the visual panel. You don't need them. Then, having a nice little module which includes just one Java class, just install it.
- Try the plugin. Now, remember the category you selected, back in step 4, when you created the wizard? If not, look in the layer.xml file, which should give you a clue. Now that you have installed your plugin, you should be able to find your new wizard in the New File wizard and invoke it from there. You should see something that looks like this:
Create the FreeMarker file template. When you click Finish above, nothing happens. That's what this step is all about. Let's create our FreeMarker template. Right-click the package where your Java class is found, choose New | Other and then, in the New File wizard, choose Other | Empty File. (You'll see a FreeMarker category, installed by the plugin that we installed in step 1 above, but let's leave that for a future article.) Type "ItsNatServlet.ftl" (or something else, so long as the extension is ".ftl"). Then... specify your FreeMarker template, as shown in the screenshot below.
And now you can see the syntax coloring and code completion provided by NetBeans IDE 6.0, via the plugin you installed at the start of this tutorial. (It is at this point that FreeMarker becomes relevant, so apologies for the time it took to get here, but this is the exact context where FreeMarker begins to be useful in this scenario.)- Hook the FreeMarker file template into the plugin. Now that our FreeMarker template is done, let's hook it into our wizard so that, when Finish is clicked by the user, it is used to create the user's file. First, open the layer.xml file and add a "URL" attribute to the file name definition of the template, pointing to the location of our FreeMarker template, and changing the extension of the file name to specify that we wll create a file with the ".java" file extension:
<file name="ItsNatServlet.java" url="ItsNatservlet/ItsNatServlet.ftl">
Back in the iterator, i.e., our Java class, look at the instantiate method:
public Set instantiate() throws IOException {
return Collections.EMPTY_SET;
}
First, set dependencies on "File System API", "Datasystems API", and "Nodes API". Then change the above method to the following:public Set instantiate() throws IOException {
String className = Templates.getTargetName(wizard);
FileObject pkg = Templates.getTargetFolder(wizard);
DataFolder targetFolder = DataFolder.findFolder(pkg);
TemplateWizard template = (TemplateWizard) wizard;
DataObject doTemplate = template.getTemplate();
doTemplate.createFromTemplate(targetFolder, className);
FileObject createdFile = doTemplate.getPrimaryFile();
return Collections.singleton(createdFile);
}Now install the module again. This time, when you complete the wizard, you will have a new "ItsNat" servlet:
If you don't have the "ItsNat" JAR files on the classpath, you'll also have... helpful red error marks in the editor.
At this point, there are several open items to explore in the next part of this series—for example, we defined a set of variables in the FreeMarker template. They were magically replaced when we created the file via the wizard. How did that happen? Also, the FreeMarker template starts with lines of code that seem to relate to a project license. But... when the file was created, there was no project license. Why? These two questions and others will be handled in the next part of this series.