• Fat Cats Boardgame
  • Wicket UI Library
  • About Me

Java and Wicket web development thoughts, tutorials, and tips

roman@coderdreams.com
Coder DreamsCoder Dreams
  • Fat Cats Boardgame
  • Wicket UI Library
  • About Me

How to create dynamic HTML markup for Wicket panels

November 9, 2019 Posted by Roman Sery wicket No Comments

One of the minor annoyances new Wicket developers run into is the seemingly inflexible static HTML markup files. Typically for each Java Panel class you would have a corresponding HTML file defining the markup. The markup might be something like this:

<wicket:panel>
    <h1>Hello World</h1>
    <input type="text" wicket:id="textField1" />
    <select wicket:id="dropDown1"></select>
    <select wicket:id="dropDown2"></select>
</wicket:panel>

The problem

The above markup is relatively static. It might be just fine for most cases, but imagine your Panel class has lots of conditional logic, or is highly reused throughout your code. Based on certain conditions, it can radically change it’s markup. In that case it would be difficult to generate the exact HTML you want.

Your Panel class must also always create the 3 Wicket components textField1, dropDown1, dropDown2 or else face the dreaded ‘Unable to find component with id ‘xxx‘ exception.

The solution – IMarkupResourceStreamProvider

Fortunately Wicket provides us with a simple and elegant solution. By modifying our Panel class to implement the IMarkupResourceStreamProvider interface, we can remove the HTML markup file and generate it from within the class exactly as we want it! Let’s look at a simple example to demonstrate the possibilities:

public class DynamicMarkupPanel extends Panel implements IMarkupResourceStreamProvider {
    @Override
    public IResourceStream getMarkupResourceStream(MarkupContainer container, Class<?> containerClass) {
        if(isSimple()) {
            return new StringResourceStream(SIMPLE_HTML);
        }

        String str = StringUtils.replaceEach(COMPLEX_HTML,
                new String[]{"{LCLASS}", "{RCLASS}", "{INNERHTML}", "{LBL}"},
                new String[]{lClass, rClass, innerHtml, lbl});

        return new StringResourceStream(str);
    }
}

Now instead of our DynamicMarkupPanel class looking to find the markup in DynamicMarkupPanel.html, it instead will call getMarkupResourceStream to generate it. In this method you have full flexibility to create the exact HTML content you wish!

The final piece of the puzzle – IMarkupCacheKeyProvider

There is one more thing we need to do in order for this to work efficiently and take advantage of Wicket’s internal markup cache. We don’t want to generate this markup each time we render the page. Because we are using dynamic markup, we need to tell Wicket how to create a cache key.

The cache key will tell Wicket under what conditions it should re-use a cached copy of the markup or create new markup. The way you create the cache key will vary for each Panel depending on it’s requirements. Let’s take a look at a simple example:

public class DynamicMarkupPanel extends Panel implements IMarkupResourceStreamProvider, IMarkupCacheKeyProvider {
    @Override
    public IResourceStream getMarkupResourceStream(MarkupContainer container, Class<?> containerClass) {
        //code from above
    }
    @Override
    public String getCacheKey(MarkupContainer container, Class<?> containerClass) {
        final String classname = containerClass.isAnonymousClass() ? containerClass.getSuperclass().getSimpleName() : containerClass.getSimpleName();
        return classname + '_' + lClass + '_' + rClass + '_' +
                (isSimple() ? 1 : 0) + '_';
    }
}

We modify DynamicMarkupPanel to implement the IMarkupCacheKeyProvider interface as well. The basic idea is to make sure that the cache key is constructed in a way that includes all the dynamic conditions used by getMarkupResourceStream(). You will notice if you are not doing it correctly because the HTML rendered for your Panel will not change when you expect it to, so double check the cache key!

Conclusion

This technique is very powerful in Wicket and can enable you to create highly reusable and performant components. It’s also a great way to cut down on Wicket page size as you may have Panels that sometimes need to create 10 Components, and sometimes only 1.

However it should be used sparingly when it really makes sense to. Usually you should try to keep your HTML and java code separate.

Have fun! 馃檪

No Comments
Share
3

About Roman Sery

I've been a software developer for over 10 years and still loving Java!

You also might be interested in

Launching LetsDefinitely.com – A dating website

Jul 28, 2020

Launching LetsDefinitely.com - A dating website

How to add a data access layer to your Wicket app using Hibernate and Spring JPA with minimal code

Dec 17, 2019

Learn how to quickly add database communication to your Wicket app using Hibernate and Spring Data JPA while writing almost no code!

How to write a JSON response in Wicket

Jan 26, 2020

Learn how to create JSON response endpoints in Wicket

Categories

  • aws
  • customization
  • database
  • debugging
  • enum
  • java
  • models
  • performance
  • projects
  • react
  • software design
  • Spring
  • tool
  • Uncategorized
  • wicket

Recent Posts

  • Rent Day
  • Self-contained Wicket Fragments
  • Pros and cons of unit testing
  • Themeable React Monopoly board
  • Please dont use client-specific release branches

Recent Comments

  • TCI Express Thanks for sharing such insightful information. TCI Express truly stands out as the best air logistics company, offering fast, secure, and efficient air express and cold chain transportation services....

    Tracking down a bug in production Wicket application 路  March 25, 2025

  • Tom Error: A zip file cannot include itself Can you please correct the plugin part so it doesn't use the same folder as input?

    Deploying Spring Boot app to AWS Beanstalk with Nginx customization 路  September 3, 2021

  • Golfman: Reality always wins I've used both Wicket and front-end JS frameworks and, having worked extensively on both, I can tell you that "Speed of development" is definitely NOT with the JS frameworks. You basically end up...

    Five reasons you should use Apache Wicket 路  August 29, 2021

  • Kiriller Sorry can not agree with you, wicket might be a well built technical framework. But the advantages of using a front-end framework like react.js and vue.js can not be beaten by Wicket nowadays. - Speed...

    Five reasons you should use Apache Wicket 路  August 23, 2021

  • Bernd Lauert Sorry but i have to refute your claims with the following arguments: 1. the Wicket community may be small but it is also very responsive, you usually get a helpful answer from the core devs on the...

    Five reasons you should use Apache Wicket 路  July 1, 2021

Archives

  • May 2021
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • April 2020
  • March 2020
  • February 2020
  • January 2020
  • December 2019
  • November 2019
  • October 2019
  • September 2019
  • August 2019
  • July 2019

Contact Me

Send Message
Prev Next