• 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

Dynamically add Wicket panels

August 8, 2019 Posted by Roman Sery wicket No Comments

A typical Wicket setup

So you’ve got a nicely structured Wicket application setup, with neatly separated Panels to group functionality. You’ve got WebPage’s that are built up by adding several Panels to them. It would typically look something like this:

<body>
    <span wicket:id="introPanel"></span>
    <span wicket:id="profilePanel"></span>
    <span wicket:id="settingsPanel"></span>
</body>
public class UserPage extends WebPage {
    public UserPage() {
        super();
        add(new IntroPanel("introPanel"));
        add(new ProfilePanel("profilePanel"));
        add(new SettingsPanel("settingsPanel"));        
    }
}

The problem

Suppose you need different implementations of ProfilePanel for each of your customers. A simple but unmaintainable way of doing this would be to use if statements, but as you can see this would get messy very quickly:

//very messy, unmaintainable
if(customer = 1)
   add(new ProfilePanel1("profilePanel"));
else if(customer = 2)
   add(new ProfilePanel2("profilePanel"));

Introducing the CustomerSpecific interface

Leveraging techniques we’ve learned in previous blog posts and reflection, we can come up with a much cleaner solution. The first step is to define an annotation that we can use to mark Wicket Panels as being specific to a customer and which Panel they are overriding, let’s call it CustomerSpecific:

public @interface CustomerSpecific {
	Class<?> replace();
	String customer();
}

We can now use this annotation to create a custom implementation of ProfilePanel for one of your customers, ‘FB’. We create a new class ProfilePanelFB extending ProfilePanel and mark it with the CustomerSpecific annotation.

@CustomerSpecific(replace = ProfilePanel.class, customer = "FB")
public class ProfilePanelFB extends ProfilePanel {
    public ProfilePanelFB(String id) {
        super(id);
        //add custom code here
    }
}

Now you might be wondering how do we add this panel to the page? We will show that soon, but there is one more step before we can do that.

Introducing PanelFactory

We need a way for our application to scan our code and find all Panels annotated with CustomerSpecific and provide a quick and simple way to get an instance of the correct Panel based on the current customer.

PanelFactory does just that. On application startup, it caches all the constructors of all the Panel’s that are marked as CustomerSpecific and provides a simple way of instantiating a Panel using the correct customer implementation.

You can check out the full code for PanelFactory on GitHub. We will show here how to use it.

Using PanelFactory to get an instance of ProfilePanel

So using the example above, how do we get an instance of ProfilePanelFB without explicitly knowing that it even exists?

addOrReplace(panelFactory.newInstance(ProfilePanel.class, "profilePanel", () -> new ProfilePanel("profilePanel")));

What the above line does is ask panelFactory to return an implementation of ProfilePanel for the current customer, with the markup ID “profilePanel”. If no implementation exists, by default, return the standard ProfilePanel.

If you put a breakpoint here, and set your environment to use the ‘FB’ customer, you will see that the return type is ProfilePanelFB!

Now your new UserPage will look something like this:

public class UserPage extends WebPage {
    public UserPage() {
        super();
        addOrReplace(panelFactory.newInstance(IntroPanel.class, "introPanel", () -> new IntroPanel("introPanel")));
        addOrReplace(panelFactory.newInstance(ProfilePanel.class, "profilePanel", () -> new ProfilePanel("profilePanel")));
        addOrReplace(panelFactory.newInstance(SettingsPanel.class, "settingsPanel", () -> new SettingsPanel("settingsPanel")));
    }
}

You can have as many implementations for all your customers as you need, without UserPage needing to know anything about them! Check out the full working sample app on GitHub.

No Comments
Share
2

About Roman Sery

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

You also might be interested in

Wicket quick tip #1: Async CSV export

Apr 5, 2020

A series of quick tips aimed at improving your productivity.

Happy holidays

Dec 24, 2019

Just a short note

autocomplete

Wicket autocomplete components with remote data

Jan 5, 2020

Autocomplete or type-ahead fields are used when the large number of options makes it infeasible to use dropdowns containing all the possible options. Let's learn how to implement them 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