Over a million developers have joined DZone.

Apache Wicket with Lambda Expressions

· Integration Zone

Build APIs from SQL and NoSQL or Salesforce data sources in seconds. Read the Creating REST APIs white paper, brought to you in partnership with CA Technologies.

The following is a post from Rodrigo Uchôa's personal blog. Here you can find the original post.

What’s up? :)

I’ve been working on some projects that thankfully use Apache Wicket for the presentation layer. It naturally occurred to me how Java’s 8 lambda expressions fit perfectly with Wicket. And not just me, the Wicket team seems to be already working on changing the API to provide support for lambdas out of the box.

This article will be more enjoyable if you already know how lambdas in Java work. If you don’t, this is a good starting point . Some knowledge in Apache Wicket is also recommended, but if you ever played with any GUI oriented API such as Swing or GWT, it should be enough to get a grasp of it.

Before we begin I just want to make a statement about why I like Wichet better than JSF. If you don’t care, just skip this part :)

My Rant With JSF

To sum it up, if you’re considering using a server-side component-based framework for a project, I see no reason to choose JSF over Wicket. Here are some of my arguments:

1- Wicket code is just easier to read and maintain

JSF forces you to have presentation logic scattered between your xHTML files and java classes (managed beans), due to all that rendered , render and so on. Wicket on the other hand enables us to just write java code. All logic is contained within the controller class, making it easier to read and maintain in my humble opinion.

Some might argue that as all other GUI oriented APIs, Wicket’s code is more verbose specially due to all the anonymous inner classes that end up being written. To me this is only partially true. The code is indeed more verbose than JSF’s Managed Beans, but to it’s still easier to read. It’s just java code in a single place. Not Java mixed with EL inside facelets pages.

As for all the anonymous inner classes , they could and can be more than ever prevented by using lambda expressions . This is what I’m showing you in this article.

2- With Wicket there’s a clearer separation of roles

Wicket is built around the premise that we can use pure HTML to build our pages. There are a few tags that need be used, but the end result is still 95% pure HTML . This makes it possible to have web designers that know nothing about Java or Wicket working side by side with developers. Designers do what they do best, and the developers just use almost entirely what they created worrying only about regular java code.

JSF is a whole different beast. You pretty much have two options: 1) Force your designers to learn JSF, which they will hate. 2) If they make pure HTML prototypes, someone will have to “re-code” them in JSF.

I know that there are a number of alternatives to deal with this matter, and they even introduced a “friendly markup” feature in JSF 2.2. Still, none of the approaches I know of are as simple as Wicket’s.

3- In Wicket extending/creating components is a lot easier

Creating a component from scratch in JSF is a nightmare. Even when talking about facelets compositions, it’s nowhere as simple as Wicket’s.

All in all, this is just my opinion. Of course that JSF gets the spotlight because it is part of the Java EE specification, and every new developer in town is looking to learn JSF, not Wicket. And while it’s certainly possible to build superb web apps with JSF, Wicket is just as capable with half of the headache.

It’s also important to note that I have nothing against the JSF team. It’s quite the opposite: the JSF expert group is filled with brilliant people. That is undeniable. I can only wonder what they could achieve if set to work in a completely different solution.

Finally, Wicket & Lambdas

Lambdas will fill the spot once filled by anonymous inner classes. Usually as in any GUI API, handling GUI events will trick you into writing anonymous classes. Here’s a simple example with Swing:

JButton button = new JButton("Save");
button.addActionListener(new ActionListener() { //anonymous class
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Button clicked");
        //Our button was clicked. Here we perform
        //everything needed to make the action
        //of clicking a button work.
    }
});
That was it. We ended up passing a state, an object, where we should be passing a behavior, a method. The code is just more verbose than it should.

With Wicket the problem is almost identical:

AjaxFallbackLink link = new AjaxFallbackLink("linkId") {
    @Override
    public void onClick(AjaxRequestTarget target) {
        System.out.println("Link clicked!");
    }
};

To ease the pain handling GUI events, using lambda expressions and a couple of helper classes we could write the same code above like this, in a single line of code:

AjaxFallbackLink link = ComponentFactory.newAjaxLink("linkId", (target) -> System.out.println("Link clicked!"));

Of course that most event processing will require much more than a simple “System.out”. So for this reason will be better off hiding these details inside a private method in the same class. Here’s a more complete code sample of how this would look like:

public class MyPage extends WebPage {
 
    public MyPage(final PageParameters parameters) {
        super(parameters);
 
        AjaxFallbackLink link = ComponentFactory.newAjaxLink("linkId", (target) -> linkClick(target));
    }
     
    //this method is called in line 6
    private void linkClick(AjaxRequestTarget target) {
        //do a bunch of stuff here
    }
}

Nailing It Down

As always I’ve set up a small project on GitHub with the complete code. You can get it here. There’s not much code, but I think it’s enough so you can have an idea an create your own lambda enabled APIs.

The project consists of a small use case for inserting users into a make believe database (the database is actually an ArrayList as you can see in the code). It looks like this. Ugly, but functional:

use-case

No mystery there. Newly inserted users are shown in the red table below, with an “Edit” link for each of them. Now let’s get to the code.

First we need some “Functional Interfaces” . You might at first be tempted to use the functional interfaces already provided by the JDK . There are a lot of them and some will indeed seem to fulfill your needs. Problem is, being a serialization freak, Wicket will complain that none of them are Serializable . So I decided to come up with my own:

TIP: None of this will make sense if you don’t know how Java’s lambdas work. Read this article first.

@FunctionalInterface
public interface AjaxAction extends Serializable {
     
    public abstract void onClick(AjaxRequestTarget target);
}
@FunctionalInterface
public interface FormAction extends Serializable {
     
    public abstract void onSubmit();
}
@FunctionalInterface
public interface StringSupplier extends Serializable {
     
    public String get();
}

Soon we will them in action. Like I said before, note that all them extend Serializable .

Dynamic Labels

One rather annoying aspect of our page is that some of the labels have to change depending on the actual action we’re performing. That is, if we’re editing an existing user, it doesn’t make sense to show “ Insert User” on the top. An “ Edit User” label fits better. The “ Save ” button below could also change to “ Update “. Keep this is mind because that’s the reason I created the StringSupplier functional interface.

Insert-Edit

The approach I’m using is to use a single HTML element and change its value as needed, not having two different ones hiding and showing when necessary. To give some perspective this is how this would normally be done:

Insert User/Update User

titleLabel = new Label("titleLabel", new Model() {
    @Override
    public String getObject() {
        if (form.getModelObject().getId() == null) {
            return "Insert User";
        } else {
            return "Edit User";
        }
    }
});

We would provide a label with an “anonymous class” as a Model. The getObject() method would then based on the current state of the “User” (our entity) model object decide if it’s an insertion or an update. What a hassle.

Using lambdas, what I’m proposing is gonna look like this (the HTML page remains the same):

Scroll right if you can’t see the whole line.

titleLabel = ComponentFactory.newLabel("titleLabel", () -> form.getModelObject().getId() == null ? "Insert User" : "Edit User");
add(titleLabel);

As you can see in line 1, we have a lambda whose expression is a ternary operator. If could be normally done with an if/else statement, but it would look uglier. I’ve already shown you the StringSupplier functional interface, now it’s time to see our helper ComponentFactory class.

Like the name suggests, it’s just a regular class with some static factory methods to create components. Here’s how our newLabel() factory method looks like:

//Remember, StringSupplier is a functional interface that returns a String.
 
public static Label newLabel(String wicketId, StringSupplier supplier) {
    Label label = new Label(wicketId, new Model() {
        @Override
        public String getObject() {
            return supplier.get();
        }
    });
    label.setOutputMarkupId(true);
    return label;
}

Buttons

Now to the “Save/Update” button. Besides the fact that its label should also change based on the form’s model state, we will also be using a lambda expression to assign an method do handle the “click event”. Normally, without lambdas, this is what we would do:

//this would go inside the class constructor
Button saveUpdateButton = new Button("saveUpdateButton") {
    @Override
    public void onSubmit() {
        //saveUpdate(User) is a private method
        //in this very same class
        saveUpdate(form.getModelObject());
    }
};
saveUpdateButton.add(new AttributeModifier("value", new Model() {
    @Override
    public String getObject() {            
        return form.getModelObject().getId() == null ? "Save" : "Update";
    }
}));
form.add(saveUpdateButton);
//this is a private method inside the same class
private void saveUpdate(User user) {
    //Logic to insert or update an User.
}

We created a Button overriding its onSubmit() method, then attached a AttributeModifier behaviour to handle the label switch. It look us 15 lines of code. Now the lambda counterpart:

Button saveUpdateButton = ComponentFactory.newButton("saveUpdateButton",
        () -> form.getModelObject().getId() == null ? "Save" : "Update",
        () -> saveUpdate(form.getModelObject()));
form.add(saveUpdateButton);

That’s it. Note that it could easily be just 2 lines, but since the first statement would be too long I decided to break it in 3. The newButton() method takes 3 arguments: a wicket id and two lambda expressions, StringSupplier and FormAction respectively. Here’s the code:

public static Button newButton(String wicketId, StringSupplier labelSupplier, FormAction action) {
    Button button = new Button(wicketId) {
        @Override
        public void onSubmit() {
            action.onSubmit();
        }
    };
         
    AttributeModifier attrModifier = new AttributeModifier("value", new Model() {
        @Override
        public String getObject() {            
            return labelSupplier.get();
        }
    });
    button.add(attrModifier);
         
    return button;     
}

Well, this is it. Hope you liked it. Leave questions below if you want.

You can get the source code here .
And again, you can find a good introduction to lambda expressions here

The Integration Zone is brought to you in partnership with CA Technologies.  Use CA Live API Creator to quickly create complete application backends, with secure APIs and robust application logic, in an easy to use interface.

Topics:

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}