You think code reuse is an elusive ideal? Wicket says think again When you’re building any kind of complex application, you want to re-use as much code as possible. The problem is, you may find yourself stymied by components that are just different enough that you have to build them from scratch. In this second installment in Nathan Hamblen’s introduction to Web development with Wicket, you’ll see how this open source, component-based Web application framework gets around such problems, greatly reducing the amount of code you need to cut and paste.While small-scale code reuse is often impractical in a traditional Web rendering path, Wicket‘s ambitiously object-oriented rendering engine fosters sharing of both user-interface logic and layout among pages. By encouraging pragmatic, everyday code reuse, Wicket brings the best of desktop application programming to the Web.This series, which began with an article on stateful and stateless modes of Wicket development, now moves on to the rendering engine that is built on that abstracted state. What does it take to make custom components, and how do they facilitate reuse? To find out, you’ll take the sample calculator application from the previous article in this series and refactor it to eliminate its redundant layout code, then proceed to apply permutations of calculators to a pair of application pages. From pages to panelsA WebPage subclass is itself a custom component: if you’ve programmed in Wicket, you’ve authored components in Wicket (no certification required). But pages are pretty monolithic. The most common way to make a portion of one page reusable is to move that part into a panel. Like a page, a Wicket panel has an associated HTML template file. It incorporates chunks of layout and functionality that can be dropped into any page of an application.In migrating functionality from a page to a panel, the first step is to create a new Panel subclass. As a normal component (not a page), the Panel must be initialized with a component identifier; your subclass constructor must call super() with an ID. For the calculator application, you’ll want a base class with two subclasses, similar to the old BasePage hierarchy, but with shared layout. Listing 1 shows the base panel class.Listing 1. Base calculator panel and constructorpublic abstract class CalcPanel extends Panel { public CalcPanel(String id) { super(id); } enum Op { ... The next step is to make subclasses from the two page variants by moving the code en masse to new panels, changing only the constructors. Listing 2 outlines the class declarations and constructors. Listing 2. Calculator subclassespublic class StatelessCalcPanel extends CalcPanel { protected BigDecimal buf = BigDecimal.ZERO; protected BigDecimal input = BigDecimal.ZERO; protected Op op; public StatelessCalcPanel(String id) { super(id); add(new CalcForm("form")); } class CalcForm extends StatelessForm { ... } } public class StatelessCalcPanel extends CalcPanel { protected BigDecimal buf = BigDecimal.ZERO; protected BigDecimal input = BigDecimal.ZERO; protected Op op; public StatelessCalcPanel(String id) { super(id); add(new CalcForm("form")); } class CalcForm extends StatelessForm { ... } } At this point, you could make similarly superficial adjustments to the markup templates and have two panels that replicate the functionality of the original two pages. But instead, in this article you’ll see an implementation that will improve on the original with Wicket’s markup inheritance, a simple technique for layout reuse that provides an extension point for subclasses.Markup: You can take it with youThe template binding mechanism for Wicket is flexible with respect to the class hierarchy. A class is not required to have a template so long as one can be resolved from a superclass. Without markup inheritance, a template found for a subclass replaces one in a superclass. With markup inheritance, the template is inserted inside the superclass template.In the example code from the first part of this series, the only difference between the two page templates was the presence of hidden form fields in the stateless version of the page. But now you’ll move the entire template to the base class, replacing the hidden fields with an extension point, as shown in Listing 3. Listing 3. CalcPanel.html: The base calculator template<?xml version="1.0" encoding="utf-8"?> <html> <wicket:panel> <form wicket:id="form"> <wicket:child/> <div> <span wicket:id="display">0</span> </div> <div> <input id="input-field" type="text" value="0" wicket:id="input" /> <input wicket:id="eq" value="=" type="submit" /> <input type="submit" wicket:id="clear" value="c" /> </div><div> <input wicket:id="div" value="÷" type="submit" /> <input wicket:id="mult" value="×" type="submit" /> <input wicket:id="sub" value="-" type="submit" /> <input wicket:id="add" value="+" type="submit" /> </div> </form> </wicket:panel> </html> The <wicket:panel> tag in Listing 3 designates the portion of the template that is applicable to the panel. While page templates are themselves complete HTML files, a panel’s active content is not. The panel tag allows outside HTML to be present for template previewing but ignored at runtime. A preview of this template appears in Figure 1.The ability to preview a Wicket component template in a regular browser, whether that component is a page or panel or something else, is a crucial advantage. It doesn’t just allow programmers to code and test layouts and client-side scripts with no delay; it also allows designers to do the same without any need for a Java development environment. The code surrounding the panel tags — just the <html> tags, in this case — is “dead” to the renderer, but usually worth maintaining for project members.Inside the panel and form tags ing Listing 3 is the <wicket:child/> element, which marks the spot for markup inheritance. In Listing 4, the stateless class’s template inserts the hidden fields it requires. Listing 4. StatelessCalcPanel.html: The stateless calculator extension template<wicket:extend> <input type="hidden" wicket:id="buf" /> <input type="hidden" wicket:id="op" /> </wicket:extend> For this child template, the panel tags are not required, as the <wicket:extend> tags serve a similar purpose. They would permit bracketing HTML for a fully previewable template, but this template has not gone that route. Because its layout is visually identical to the base templates, there is no utility in a separate preview.Sharp-eyed readers may have noticed that the <?xml ...> tag that was present in all the other templates does not appear in this one. That tag is optional and is not, as you may have supposed, intended for a client’s browser. Rather, it serves to tell Wicket the character set of the template file (necessary, as those files contain non-ASCII symbols) so that it can be transformed to whatever character set is used for the actual response. In that response, the encoding is declared in HTTP headers and not in any HTML tag. Only in template preview does the tag inform a browser.As mentioned previously, Wicket’s template resolution mechanism is not picky: even though the <wicket:child> tag in a superclass template implies markup inheritance, you needn’t provide any template for the StatefulPage subclass. That portion where a child template would appear is simply left blank. A capsule victory?Looking back over the Java and HTML code, you may be surprised that the template component tags, identified by the wicket:id attribute, appear in a different template from the class that adds them. Only the buf and op hidden fields appear in the same-named class and template. How does this work? And isn’t it bad?To sort out the situation, keep in mind that the component hierarchy is distinct from the class hierarchy. When you call add(new Something("some_id")) in a subclass, it is the same as calling it in a superclass. The code is building up a tree of components structured by component identifiers; separately, one or more markup templates are assembled into an overall template for the instance where tags with wicket:id attributes must correspond to the hierarchy built up in code. In this process, the class or template file in which the reference occurs has no bearing.But there are some drawbacks to exploiting this flexibility. Readability suffers when a bound component can not be found in an adjacent file of the same name. Furthermore, if CalcPanel were a class you wanted to share, other coders would need to build a component hierarchy matching an external template. That’s not convenient, and not at all encapsulated. It would be better from that perspective to add all the components that appear in the base class template within the base class constructor. That would be tricky in this instance, where a different base class is used for the stateless form, but nearly anything is possible with override-able callbacks. (You’ll see an example of this later.) On the other hand, maybe you don’t want CalcPanel to be a base class for all the world to use. Markup inheritance is just a convenient tool for factoring out markup, and that’s what CalcPanel pragmatically does with it: now there is no duplication of the calculator markup. While markup inheritance blurs the conceptual lines between class and component inheritance, its realization is entirely up to the programmer. In this case, it isn’t worth conflating the stateful and stateless logic in the base class, and makes no difference to users or extenders of the two concrete classes.Putting panels into pagesAt this point, the calculator application has two complete calculator panels, but no way to render them to a Web browser. For that, you’ll need the pages back. (As a side note, markup inheritance is available to pages just as it is to panels. It would have been possible to factor out markup within the original pages of the application without turning them into panels, but as a panel the calculator can be added anywhere on any page.)The first step is to make a new application home page. Recall from the previous article in this series that the stateless variant requires no server-side session; as a result, it’s a better choice for the page that would see the most views (and bounces). Listing 5 shows the very simple page class. Listing 5. A front page classpublic class FrontPage extends WebPage { public FrontPage() { add(new StatelessCalcPanel("calc")); } } Because it has no components that require state, this page is stateless, and checking cookies will confirm that. But the layout template, shown in Listing 6, may hold a few surprises.Listing 6. Layout template<?xml version="1.0" encoding="utf-8"?> <html> <head> <title>Calculator — Front Page</title> </head> <body onload="document.getElementById('input-field').focus()"> <h1>Calculator — Front Page</h1> <div wicket:id="calc" class="calc"> <div> <span>0</span> </div> <div> <input value="0" id="input-field" type="text" /> <input value="=" type="submit" /> <input value="c" type="submit"/> </div><div> <input value="÷" type="submit" /> <input value="×" type="submit" /> <input value="-" type="submit" /> <input value="+" type="submit" /> </div> </div> <wicket:link>Inside Page</wicket:link> </body> </html> After you did all that work to factor out the markup, you’re probably wondering why it appears once again on this page. In fact, it’s entirely optional; the markup inside a tag referring to a panel is ignored. But if you want the page to preview correctly, the panel markup must appear on it. If preview is not important to you for a particular page, don’t copy and paste the markup into it.There is a crucial difference between copying and pasting for preview and doing so for execution: if the real template is later changed to reflect a new style or to fix a layout bug, users never see the old layout or hit the same bug again. It’s fixed once and fixed everywhere, without any need for search and replace. But the preview-only code may lag behind template changes, and often does; it’s up to project members to maintain this code well enough to be useful to themselves. With that rationalization out of the way, turn your attention to what’s new in this template: <wicket:link>. This is a handy tag that initiates Wicket autolinking. It can surround one or more other tags, and triggers a runtime adjustment of href attributes to point to real, live resources. When previewing, they point to real, static project sources. For this page, the link provides a click through to InsidePage.html, which is going to be the template for the next page. Figure 2 shows a preview of this stateless front page, which is identical to its live rendering.Putting a spectrum of panels onto a pageYou could add a StatelessCalcPanel to any page and it would render and work just the same everywhere. But suppose, for the sake of example, that you want to have a number of calculators on one page, each with independent state. In that case, the StatefulCalculator is required. A single form submission for one of the calculators would not contain the entire state of the page.This plan calls for a number of calculators in sequence, begging the question of how to do a for loop in a Wicket template. There is a Wicket component called Loop, but it’s rarely used in practice (I haven’t used it once). There are slightly deeper abstractions that do more work on their own. ListView is the tool to loop through simple List objects in a template. It renders its body in a callback, once for each element of the list. Suppose that you want to render a calculator panel once for each hue of the spectrum, as traditionally defined by the mnemonic Roy G. Biv. Since these color names are recognized by browsers, a list of names is all that’s needed for data. By passing this list to a ListView, local code can operate on each element of the list, as shown in Listing 7.Listing 7. InsidePage defines a List and its ListViewpublic class InsidePage extends WebPage { private List<String> colors = Arrays.asList( "red", "orange", "yellow", "green", "blue", "indigo", "violet"); public InsidePage() { add(new ListView("calcs", colors) { protected void populateItem(ListItem item) { AttributeModifier color = new AttributeModifier("style", new Model( "background: " + item.getModelObject())); item.add(new StatefulCalcPanel("calc").add(color)); } }.setReuseItems(true)); ... The populateItem() abstract method of ListView is often defined inline, in an anonymous subclass. Its ListItem parameter is the container for any sub-components, and its model object, obtained through item.getModelObject(), maps to the current element of the list, whether it’s a String or a user-defined class. In this definition of populateItem(), the current list element is appended to background: (with a trailing space) to create a style attribute setting the background of the current calculator panel. AttributeModifier is a Wicket behavior, something that can be added to any component to change the way that it renders or responds to user action.The call to setReuseItems() causes the ListItem components to be retained for future requests, which is necessary for most stateful components. By default, a ListView will discard its item components and rebuild them from the source list upon each rendering, which ensures that the list representation is up to date. Because this color list never changes, there is no such concern with the sample application; if there were, it would be necessary to call removeAll() on the list whenever the list contents changed in such a way that different components were required. The next step is to define the layout of calcs in the InsidePage page template. Listing 8 shows that portion of the template.Listing 8. ListView portion of InsidePage.html<div wicket:id="calcs"> <div wicket:id="calc" class="calc" style="background: red"> <div> <span>0</span> </div> <div> <input value="0" type="text" /> <input value="=" type="submit" /> <input value="c" type="submit"/> </div><div> <input value="÷" type="submit" /> <input value="×" type="submit" /> <input value="-" type="submit" /> <input value="+" type="submit" /> </div> </div> </div> <wicket:remove> <div> <div class="calc" style="background: orange"> <div> <span>0</span> </div> <div> <input value="0" type="text" /> <input value="=" type="submit" /> <input value="c" type="submit"/> </div><div> <input value="÷" type="submit" /> <input value="×" type="submit" /> <input value="-" type="submit" /> <input value="+" type="submit" /> </div> </div> </div> </wicket:remove> Again, the listing contains dead code to render the calculator, including a portion surrounded by <wicket:remove> tags. At the top of Listing 8 is the calcs element that is bound to each ListItem. There is no template element for the ListView itself, which is a bit of a brain teaser but in the end saves you the trouble of naming and binding an unnecessary wrapping element. Instead, the template element matching the identifier of the ListView is repeated for each element of the list.In this example, there is one sub-component per list item: the StatefulCalcPanel identified by calc in the populateItem() callback in Listing 7. The list element template is generally made up to preview the same as the first element of the list; here, it’s given a red background. Following that in the <wicket:remove> element (the contents of which are ignored by the template engine) is a calculator with an orange background (the second element of the spectrum list). With repeating elements in Wicket templates, you usually enter only enough of a mock-up to make sure that the layout works, and in this case two is good. With a few simple style rules, each calculator will appear in its own colored box, flowing across the screen from left to right. Listings 9 and 10 show how to add an autolinked stylesheet to the page.Listing 9. InsidePage.html head with stylesheet autolink<head> <title>Calculator — Inside Page</title> <wicket:link><link rel="stylesheet" href="InsidePage.css"></wicket:link> </head> Listing 10. InsidePage.css source in same directorydiv.calc { float: left; padding: .5em; margin: .5em; } The genius of autolink is well demonstrated here, where the stylesheet is applied in both Figure 3’s preview and live rendering with no extra application code.Figure 3. InsidePage.html rendered as previewThat’s all it takes to render a working calculator for Roy G. Biv. Each calculator maintains its own state, so that the page as a whole will respond correctly to the back button. The user may add 2 and 2 on the red calculator, then divide 6 by 3 on the green calculator; after those four submit requests, both calculators will display 2. Pressing the back button reverses the operations in last-in, first-out order: first the green and then the red. This is heavy-duty use of Wicket’s simulated application state, as described in the previous article in this series; it would be very difficult to achieve the same effect without server-side state. One feature that is important to the usability of the calculator is pre-selection of the current calculator’s input field after each request. This was easily accomplished for previous incarnations of the application, which contained only one input field per page; but the new version required some fancy coding in StatefulCalcPanel, which you can examine in the downloadable source. This article will carry on to explore one more technique in Wicket’s component reuse. The universal socketPanel reuse is often driven by a need discovered late in the development process. It isn’t possible to anticipate every potentially desired use and appearance for a panel, but it’s easy enough to go back add them later. In this instance, imagine that you suddenly need to a add a square root button to the end of the button list, while the only markup extension point in the CalcPanel base is in the wrong place, at the top of the form.Don’t panic! You can still change the base panel. Listing 11 shows a simple alteration to the template.Listing 11. Portion of CalcPanel.html with an operator socket<input wicket:id="sub" value="-" type="submit" /> <input wicket:id="add" value="+" type="submit" /> <span wicket:id="opSocket"></span> And Listing 12 provides a base method to produce empty components for that socket. Listing 12. Base implementation of opSocket in CalcPanelprotected Component opSocket(String id) { return new EmptyPanel(id); } Finally, each of the subclasses that actually builds the component must call the base method and add its result, as shown in Listing 13.Listing 13. Adding the opSocket, in both StatefulCalcPanel and StatelessCalcPaneladd(opSocket("opSocket")); Now both concrete calculator classes are amenable to any extension of their line of operational buttons, including the desired square root button.Listing 14. SqrtCalcPanel definition with square root operation panelpublic class SqrtCalcPanel extends StatefulCalcPanel { public SqrtCalcPanel(String id) { super(id); } @Override protected Component opSocket(String id) { return new OpPanel(id); } class OpPanel extends Panel { public OpPanel(String id) { super(id); add(new Button("sqrt") { @Override public void onSubmit() { input = buf = new BigDecimal(Math.sqrt(input.doubleValue())); } }); } } } In Listing 14, SqrtCalcPanel constructs itself exactly as normal, but with an overridden opSocket() method that returns a non-empty panel. OpPanel is declared as an inner class of SqrtCalcPanel in order to access its protected input and buf fields; inner classes, like anonymous subclasses, are common in Wicket programming. This one, yet another panel, adds a button to itself that performs a square root function on the calculator’s input.The SqrtCalcPanel does not change the structure of its superclass’s component hierarchy and so does not require a new template. It is the inner panel, whose name resolves to SqrtCalcPanel$OpPanel, that requires the template shown in Listing 15.Listing 15. SqrtCalcPanel$OpPanel.html template file<?xml version="1.0" encoding="utf-8"?> <html> <div> <div> <span>0</span> </div> <div> <input value="0" type="text" /> <input value="=" type="submit" /> <input value="c" type="submit"/> </div><div> <input value="÷" type="submit" /> <input value="×" type="submit" /> <input value="-" type="submit" /> <input value="+" type="submit" /> <wicket:panel> <input wicket:id="sqrt" value="√" type="submit" /> </wicket:panel> </div> </div> </html> This template includes only a single active line, which lies between the <wicket:panel> tags; for reasons already discussed at length, it also contains extensive bracketing code, as you can see in the listing. The template previews as shown in Figure 4.Finally, this calculator with a square root button is added after the list of spectrum-colored calculators in the inside page using techniques that should now be familiar, with a gray background statically applied in the page template. Figure 5 shows the complete page, with all of the calculators visible and some of them in a non-zero state.Figure 5. Inside calculator page, activeA spectrum of applicationsIn this article, you’ve reused Wicket components to create a whimsical array of colored calculators; of course, the concept applies equally well to more practical applications. Who hasn’t coded blocks of active HTML that are supposed to look and act the same on many different pages, except on one particular page where they should have a dotted border and contain an extra active doo-dad? Wicket gives you the tools to persevere in software reuse, even against business requirements that seemingly want to thwart it. That is something worth getting excited about.The next and final article in this introductory series on Wicket will answer the question that is surely burning in the minds of everyone who codes for a living: how exactly do I hook this thing up to a database?Nathan Hamblen is a career software programmer who codes primarily in Java. In his spare, time he works on the Databinder toolkit for Wicket and writes Coderspiel, a programming Weblog. Open SourceSoftware DevelopmentWeb DevelopmentJavaDevelopment Approaches