Geertjan's Blog

  • April 8, 2007

Lessons Learned from the WebWork Framework (Part 1)

Geertjan Wielenga
Product Manager
I've taken a small diversion prior to beginning to look at Grails support. I had a few unanswered questions, such as how to create new source roots programmatically for a framework. So, I've been looking at WebWork. Even though it seems as if WebWork has been deprecated in favor of Struts 2, I thought it would be interesting to see how far I'd get with creating some support for it, and to then return after that to Grails. (Or, in fact, to then begin Grails.) The thing with framework support in NetBeans IDE is that... it really is a pretty straightforward formula. Once you've gone through the process a few times, you kind of internalize what needs to happen. (And then cut, paste, and tweak, a lot.) Frameworks aren't all that different when it comes to tooling support in NetBeans IDE. But you can have fun with it and be as creative as you like.

Throughout the creation of my WebWork module, I leaned very heavily on the Web Framework chapter in the forthcoming Rich Client Programming book. As someone who is in the unique position of having written as well as used the Web Framework chapter, I can honestly say that it is very useful. Several things are omitted (such as how to change web.xml and project.properties) but the accompanying sample provides those bits of code... and I am planning to provide a 'Framework Support Utility Methods' supplement to the book's site. We were planning to provide supplements and updates there anyway, and wouldn't it be useful to have a simple addendum that provides utility methods for common tasks, such as how to add a filter programmatically to the web.xml file?

Anyway, my work with this support module for WebWork has resulted in me learning three brand new things, i.e., things I never knew before. Firstly, I learned how to validate fields in the framework configuration panel, so that, as shown in the screenshot below, the two text fields must be filled in, otherwise an informative red error message appears and the Finish button is disabled:

The second thing I learned, for the first time, was how to create new source roots programmatically. In the screenshot above, you can see how 'Spring' or 'Hibernate' can be selected. When selected, a new source root is created (and related libraries are put on the classpath). But how to programmatically create the new source root? First, a pic to show you what I mean:

Here, I selected both checkboxes, and so now have two new source roots. How is this done? Here's the code for creating the Hibernate source root (called from the FileSystem.runAtomicAction's run method):

private void writeHibernateSourceRoot() throws IOException {
//Create new root:
newSourceRootFolder = FileUtil.createFolder(targetRoot.getParent(), "hibernate");
//Add root to project properties:
FileObject projectprop = project.getProjectDirectory().getFileObject(AntProjectHelper.PROJECT_PROPERTIES_PATH);
EditableProperties ep = loadProperties(projectprop);
ep.setProperty("src.hibernate.dir", "${source.root}/hibernate"); // NOI18N
storeProperties(projectprop, ep);
//Add root to project.xml:
FileObject projectXml = project.getProjectDirectory().getFileObject(AntProjectHelper.PROJECT_XML_PATH);
String content = readTextResource(projectXml.getInputStream(), "UTF-8"); //NOI18N
String find = "<root id=\\"src.dir\\" name=\\"Source Packages\\"/>"; // NOI18N
String endLine = System.getProperty("line.separator"); //NOI18N
if (content.indexOf(find) > 0) {
StringBuffer replace = new StringBuffer();
replace.append(" <root id=\\"src.hibernate.dir\\" name=\\"Hibernate\\"/>"); //NOI18N
content = content.replaceFirst(find, replace.toString());
writeFile(projectXml, content, "UTF-8"); //NOI18N

(Note: The code above for changing project.xml is probably unsafe, I am trying to find out if this is the best way to do it and, if not, what the best way is.)

Here, we first create a new folder called "hibernate", we then add a new property to project.properties, and finally add a new entry to project.xml. A few utility methods are called above, but this method gives the basic idea.

The third, and final, new thing I learned was how to programmatically register a DTD file, so that code completion is available in WebWork's xwork.xml file. First, you need to put the DTD into a package in your module, such as in a resources subpackage. Next, define the new catalog in a class that implements CatalogReader, CatalogDescriptor, org.xml.sax.EntityResolver. For examples, see the Struts module, which was the basis of my own implementation. Finally, register the class in the layer.xml:

<folder name="Plugins">
<folder name="XML">
<folder name="UserCatalogs">
<file name="org-netbeans-modules-web-webwork-framework-WebworkCatalog.instance">
<attr name="instanceCreate" newvalue="org.netbeans.modules.web.webwork.framework.WebworkCatalog"/>
<attr name="instanceOf" stringvalue="org.netbeans.modules.xml.catalog.spi.CatalogReader"/>

So now my xwork.xml file has code completion, automatically, without the user needing to do anything for it:

Especially the source root thing is interesting. That will definitely come in useful with Grails, which (from everything I've seen) is typically organized with multiple source roots.

So, now with these interesting lessons learned, let's have a look at Grails...

Join the discussion

Comments ( 2 )
  • Paris Apostolopoulos Monday, April 9, 2007
    Hello Geertjan, I am very happy to see that most probably Netbeans 6.0 I guess will support Struts 2 (which is 90% webwork). Excellent!
  • deep Monday, June 4, 2007
    ok very nice topic
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.