Geertjan is a DZone Zone Leader and has posted 468 posts at DZone. You can read more from them at their website. View Full User Profile

Interview: How Wicket Does Ajax

04.25.2008
| 67816 views |
  • submit to reddit
The enhancements that Ajax brings to the web might not be your cup of tea, because of JavaScript. Either because you find it too complex or because you just don't like it. Wicket solves this problem by letting you add Ajax functionality to web applications without writing a single line of JavaScript. In effect, Wicket takes all the pain out of Ajax, delivering all its benefits directly to the Java developer via Wicket's simple all-Java programming model, which has the added bonus that you can encapsulate Ajax behavior in reusable Wicket components. Below, some of the guys behind Wicket tell you all about it in some detail.

Hi all! Firstly, please tell us who you are and your role in the Wicket project.

Jonathan. Hi, I'm Jonathan Locke. I founded the Wicket project. I was responsible for the initial design and the majority of the initial implementation. I also selected the initial team, which (with a few happy additions) still runs the project today. I was very active as a committer and in building the community for the first two years but have since become more of a user, very-interested observer and cheerleader.

Eelco. Hi. My name is Eelco Hillenius and I've been involved in Wicket since right after Jonathan opened it up for more people in 2004. I'm also the co-author of Wicket In Action. I've worked on many parts of the code base, like most members of the team. The things I'm most proud of are some of the ideas I contributed, like markup inheritance, header contributions (more on that below), and the idea to base our Ajax support on behaviors (which back then were just attribute modifiers). Without the rest of the team, though, it wouldn't have been more than just some half worked-out ideas. But that's great about our team; I feel we complement each other really well.

Igor. My name is Igor Vaynberg. I have been working on Wicket since late 2005. I have worked on all areas of Wicket, from low-level request processing to high-level components, such as the DataTable. Back in the day I wrote Wicket's first internal Ajax implementation, which has improved over time to what it is now, with the help of our talented team. Now that Wicket's core concepts have evolved to the point where most of the team is comfortable with them, I mainly work on improving our API and abstractions.

What, to you, is the central promise that Ajax brings to web applications?

Eelco. There are two things to it as far as I am concerned. The first is the improved user experience because updates can be smaller and quicker and largely take place in the background in an asynchronous fashion.

The second is the improved programming model it can bring. HTTP is a stateless protocol that was designed for a web of interlinked documents. It was never designed to run applications. Interesting GUIs are stateful. Trees, tabs, sorted lists, etc. Though many people probably don't realize this, developing interesting GUIs got a lot easier with Ajax because it enables you to do fat, stateful client server programming again. Interestingly, Wicket actually provides the same kind of programming model without needing Ajax, but instead using some server side memory.

Igor. The promise is that of faster, more responsive user interfaces. Ajax requests usually carry a smaller payload and since more than one can be executed in parallel the UI can seem more responsive to the user. In Wicket, for example, this means the ability to render only a small subtrees of the component hieararchy that makes up the page.

Another advantage is that Ajax requests do not completely refresh the page, so state can be kept between requests in the DOM tree on the client - which scales extremely well as far as keeping state in a web application goes.

Jonathan. Ajax yields faster responses for users. If the Internet and server resources were faster, the full-page refresh model would work perfectly and nobody would care about Ajax. In some ways, Ajax is a stopgap measure, like "optimized redisplay" was for terminal-based editors more than 20 years ago. Today, we don't really care how optimally Eclipse draws our screen because it's so incredibly fast that 30% better or worse is probably hard to even see with the human eye. But put a 300 baud modem in the middle of the display loop and suddenly you'll care very much!

So Ajax is not terribly interesting in the long term. It's there to plug a temporary hole and it's quite useful for that, at least for the time being.

What about those people that think Ajax is a dirty hack and you should not misuse the web like that?

Eelco. I think they should think back about how the internet initially got it's growth by hijacking telephone lines, something they were never designed for. Ajax is not the perfect everlasting solution to things, but it is a great trick for now and people enjoy slicker and faster end-user interfaces and improved productivity as a result of it.

Igor. Until there is another universally accepted and available thin client, other than the browser, we will have to stick with dirty hacks!


That's cool. But Ajax is not much fun for Java developers. First you've got to learn JavaScript.

Eelco. The worst thing about JavaScript is that it is not statically typed, so if you need to maintain a lot of JavaScript code you'll need to be very disciplined (and your team members as well) or you'll end up in maintenance hell. Other than that though, you can actually do pretty cool stuff with it. It is a more powerful language than many people think it is.

Anyway, Wicket hides much of that for you. Yes, you can create Ajax applications with Wicket without ever writing a single line of JavaScript. The autocomplete component for instance, which uses Ajax to pop up a list of choices in a text field while you type, can be used like this:

AutoCompleteTextField myField = new AutoCompleteTextField("ac", new Model("")) {
protected Iterator getChoices(String input) {
return myService.getPossibleChoices(input);
}
};
As you can see, no JavaScript, and in fact it works exactly like non-Ajax components work. However, I think that the real cool thing about Wicket's Ajax implementation is that you can encapsulate such behavior in self contained components. That enables you to write Ajax components that you can embed in a page without needing any additional configuration to make it work. The auto complete text field above is a good example of that.

Igor. Learning JavaScript is not hard, what is hard is learning FireFox JavaScript, IE6 JavaScript, IE7 JavaScript, Opera JavaScript, WebKit JavaScript, etc. The differences are subtle but can cause huge hang ups and are very annoying to Java developers who are used to Java being much more consistent. Another pain point is the lack of a really good JavaScript debugger, which is a tool Java developers take for granted.

The nice thing about Wicket's Ajax support is that we have gone through this pain and built JavaScript that works in all major browsers, so our users dont have to. With a few lines of Java code, you can connect a JavaScript event, such as "onclick" or "onchange", to a server side callback, which in turn can update one or more parts of the client's DOM tree with new markup. For example, we can easily replace an existing Link component, which generates a normal server-side callback, with an AjaxFallbackLink component that uses Ajax when it is available but gracefully degrades to a regular server side callback when Ajax is not available, all without the user having to do anything.

For example, if we take the usecase of a table showing a list of users, a regular delete user link may be implemented like so:
Link<User> deleteUserLink=new Link<User<("delete", userModel) {
protected void onClick() {
final User user=getModelObject();
database.deleteUser(user);
// nothing further to do, let wicket repaint the current page
}
}
Here is the pure Ajax version:
Link<User> deleteUserLink=new AjaxLink<User>("delete", userModel) {
protected void onClick(AjaxRequestTarget target) {
final User user=getModelObject();
database.deleteUser(user);
// tell wicket to repaint the table only
target.addComponent(table);
}
}
And here is the fallback version:
Link<User> deleteUserLink=new AjaxFallbackLink<User<("delete", userModel) {
protected void onClick(AjaxRequestTarget target) {
final User user=getModelObject();
database.deleteUser(user);

if (target!=null) {
// ajax callback, tell wicket to repaint the table only
target.addComponent(table);
} else {
// regular callback, ajax not available, repaint the current page
}
}
}

All the Ajax goodness without a line of JavaScript. Here's another example: suppose I have two DropDownChoices (select boxes) on the page, whose models are linked so that the selection in the first dictates the options available in the second (this is usually called "linked select boxes"). Suppose also I now want to make the select boxes update via Ajax all I have to do in Wicket is:

private static void linkDropDownChoices(DropDownChoice first, final DropDownChoice second) {
second.setOutputMarkupId(true); // make sure second select outputs its markup id attr
first.add(new AjaxFormComponentUpdatingBehavior("onchange") {
protected void onUpdate(AjaxRequestTarget target) {
// when onchange is triggered on first, repaint the second
target.addComponent(second);
}
});
}
This example is available live here. As you can see, I have created two linked select boxes that update via Ajax, without writing Javascript or knowing anything about how Ajax works in the browser.

Jonathan. I may be the world's worst JavaScript coder. I hardly know a line of JavaScript and I can usually find a way to screw up the few lines I do write. I probably would not do Ajax at all without Wicket's simple all-Java programming model for Ajax.

But doesn't GWT do something like that too? What's the difference and why?

Igor. GWT builds a fat client that happens to use the browser as its execution environment. Wicket builds a traditional thin-client web-application that runs on the server. Example advantage of fat clients is that they can tap into the resources of the client PC they are running on (such as memory to store state) and thus scale much better for extremely large numbers of users. Example advantage of thin clients is that typically the data store that backs the application is on a very fast local connection and thus thin client applications do not require as much optimization of queries and take advantage of user-specific data locality and caching much easier.

Jonathan. In my limited understanding, GWT simply solves a different problem from Wicket. GWT seems to be targeted at browser-hosted applications while Wicket is a traditional server-side web framework. Each architecture has its advantages. GWT is probably less round-trippy and its use of client resources ought to give it certain scaling advantages. The downside of the GWT model is that you'll spend a lot more time dealing with the fact that your application is running on a client system and not on your server. Also, since Wicket doesn't push state to the client, it is secure by default and the development effort may be easier (depending on what you're doing), as your model doesn't need to be transported anywhere.

Eelco. GWT is a very different framework. Wicket still assumes that you want to build at least part of your application the 'old fashioned' way, so that it will work without JavaScript, turn up in search engines, can be bookmarked, etc. GWT produces something that is more akin to applets; independent applications that happen to be hosted on web pages.

Are there other typical Ajax-related problems that Wicket deals with?

Jonathan. As Igor pointed out above, Wicket has a very clever set of "fallback" components which are Ajaxy when the browser supports JavaScript, but fall back to full page refreshes when JavaScript is absent. This is incredibly useful.

 

Igor. Wicket takes care of users having to marshall and unmarshall data between server and browser by working around the problem. Instead of sending data to the client Wicket renders the components on server side and sends the rendered markup. This might not be as efficient, but it sure makes it much easier and faster to develop ajaxified behaviors. For example, if one wants to update a panel that shows user information on the client via Ajax all that is necessary is to tell Wicket that the panel should be updated. There is no marshalling the User object into a JSON representation, and no unmarshalling it on client, neither is there code to manipulate the DOM on the client.

How does it all work under the hood? Somewhere there's got to be Javascript, even if way under the hood.

Igor. Because Wicket Ajax works by sending rendered markup rather than raw data to the client, the amount of JavaScript needed to make this work is significantly reduced and is completely reusable for most usecases. Wicket provides this JavaScript and abstracts its use via much higher level Java components and code.

Can you describe Wicket's Ajax programming model a bit, in relation to the long list of Ajax classes in my editor's auto complete:

Igor. Without getting too low-level, Wicket's Ajax API centers around behaviors which initiate Ajax callbacks, and the AjaxRequestTarget which is used to build the response. The neat thing about behaviors is that they can be added to any component and provide functionality in an orthogonal manner (without the component being aware).

There are a couple of central behaviors that provide Ajax functionality. The most basic one is the AjaxEventBehavior, which allows initiation of a callback when a JavaScript event occurs (such as "onclick"). Extending that, there are AjaxFormComponentUpdatingBehavior, which allows updating of any single form related component, and AjaxFormSubmitBehavior, which submits and updates an entire form over Ajax. There are a slew of other Ajax behaviors that Wicket provides, but they are mostly subclasses/specializations of the aforementioned AjaxEventBehavior.

To give a short example: lets say I have a TextField that I would like to have an Ajax callback for when a Javascript "onblur" event occurs:

TextField textfield=new TextField("email");
textfield.add(new AjaxFormComponentUpdatingBehavior("onblur") {
protected void onUpdate(AjaxRequestTarget target) {
System.out.println("current value of the textfield is: "+getModelObject());
}
}

The other part of the API is the AjaxRequestTarget, as I have mentioned before. Callbacks provided by Ajax behaviors create the target and provide it as the callback argument. The user that implements the callback can then use this target object to construct the Ajax response, which involves letting Wicket know which components need to be repainted, and if there is any additional JavaScript the user would like executed as part of the response.

All other classes that you see listed in the screenshot are convenience classes. So, for example, instead of the user having to construct a Link component and add an AjaxEventBehavior to its "onclick" event every time, we provide an AjaxLink component instead which encapsulates this code for the user.

I think that's the five minute version of Wicket's Ajax support!

How did the Ajax side of Wicket come about?

Jonathan. Someone (I think Eelco, maybe) said "hey, we need to support this Ajax thing". I had no idea what it was, so I read a couple of articles and thought "oh, partial page updates. okay." Then a variety of people commented that Wicket should have been designed from the ground up as an Ajax framework. This concerned me for a few hours, but after a bit of thought, I realized we could do partial page updates without changing the architecture almost at all. I made a couple of general suggestions for how to approach the problem and other people ran with it.

I find myself growing more and more comfortable with Wicket's ability to solve unanticipated problems like Ajax. Just last weekend, I was talking to some semantic web researchers about RDFa support when I realized that not only can you do semantic web in Wicket, but you can create a whole data-driven semantic web in maybe a couple hundred lines of code. Why? The underlying architecture is sound and built for extensibility.

To approach the semantic web, you can simply install a ComponentInstantiationListener to hook component creation and in that hook add a POJO-attribute-driven Wicket behavior which introspects on the POJO model and sets various well-known RDFa tag attributes. Voila! Instant RDFa support. But this nifty little hack is not a unique experience with Wicket. People are using Wicket for all kinds of purposes I never originally intended. It's a recurring thing and it's exciting to watch. I find myself surprised over and over again with just how far disciplined OO design can take you.

Eelco. We already had 'header contribution' support in place, which is the most important enabler for Ajax applications. Header contribution is the term we use for the ability of components to contribute markup to the header section of the page(s) these components are embedded in. Say for instance that I'd want to use Scriptaculous to 'blink' a label after a link is clicked. Without header contribution, I'd have to make sure that pages include the proper JavaScript includes. But with Wicket, I can do that in any component without having to worry what page it will live in. Look at this example (just from the top of my head, there may be a bug in it):

abstract class UpdatingTextField extends TextField {
@SpringBean UpdateService updateService;

public UpdatingTextField(String id, IModel model, Class type) {
super(id, model, type);
add(HeaderContributor.forJavaScript(UpdatingTextField.class, "prototype.js"));
add(HeaderContributor.forJavaScript(UpdatingTextField.class, "effects.js"));
add(new AjaxFormComponentUpdatingBehavior("onchange") {
protected void onUpdate(AjaxRequestTarget target) {
updateService.save(getObjectToUpdate());
target.addComponent(UpdatingTextField.this);
target.appendJavascript("new Effect.Highlight($('" + UpdatingTextField.this.getMarkupId() + "'));");
target.appendJavascript("new Effect.Fade($('" + UpdatingTextField.this.getMarkupId() + "'));");
}
});
}
protected abstract Object getObjectToUpdate();
}

That's a reusable text field that will 'blink' once when a change is detected and saved. To use this component, you don't even have to know it uses Scriptaculous internally. The two calls add(HeaderContributor.forJavaScript("...") will prompt any page this component is placed in, either directly or as part of some other component, to write out script inclusion tags in it's header section (and of course, Wicket will try to filter out duplicate contributions). In this case, the inclusions would reference two JavaScript files placed in the same package as where UpdatingTextField resides.

So, header contributions facilitate that you can create components that are truly self contained, which is important if you want to hide implementation details like how a JavaScript/Ajax library should be initialized, etc. We gradually built on that, extending behaviors - Wicket's composition mechanism - so that they could receive requests. We then built support for Dojo and Scriptaculous, but after a while wrote our own tightly integrated and efficient Ajax engine.

Igor. When Ajax became popular more and more of our users wanted to see support for it built into the framework to make its use as transparent and as easy as possible. After a few tries of providing Ajax support by integrating with other JavaScript frameworks such as Dojo and Scriptaculous we came up with the idea of sending over rendered markup rather then data. No framework supported that usecase very well at the time, so we rolled our own implementation that was optimized for our usecases. There are still community-driven Wicket projects that integrate with JavaScript libraries and provide higher level client-side functionality such as tooltips, date pickers, drag and drop, etc.

It's in the 'extensions' JAR, not the main one, why?

Eelco. It actually is since 1.3. Before that, it had to prove itself.

 

Igor. Wicket's Ajax support is in the main jar and is completely integrated into the core project. Extensions provides higher level Ajax components in the same way as it provides higher level non-Ajax components.

What are the highlights of Ajax in Wicket, in your opinion?

Jonathan. The main highlight from my viewpoint is that I can avoid learning JavaScript, which is a truly horrid thing. Of course, my problem is not just with JavaScript, but with typeless languages in general (when used to build substantial applications), but that's a whole separate discussion.

Eelco. The fact that you can encapsulate Ajax in self contained components. My favorite part of Wicket's Ajax is really how easy it is to replace a component on the fly. I typically create the Ajax components I need from scratch (base classes rather).

Igor. Its ease of use and lack of learning curve. My favorite thing is being able to easily compose any of these cool small classes into larger, higher level reusable components. Also, one simple line of Java code makes my StatisticsPanel refresh via Ajax on the client every five seconds without the panel knowing anything about it.

StatisticsPanel panel=new StatisticsPanel("stats");
panel.add(new AjaxSelfUpdatingTimerBehavior(Duration.seconds(5));

How has the reception been for Ajax and Wicket?

Jonathan. I get a steady stream of emails from users who have suddenly seen the light (usually after banging their heads against Struts or some other framework for a while). I also see posts all over the Internet singing the praises of both Wicket and Wicket Ajax support. I think the reception has been so good because Wicket fills a pretty terrible hole in the Java space. I think maybe Wicket is just the stateful, object-oriented, Swing-like web framework we all deserved in the first place.

Eelco. It's been great. People like it, and without Ajax support, Wicket probably wouldn't have caught on the way it did. Many people really like the fact that it is optional; they can use it where appropriate, but leave it where they don't want it.

Igor. Phenomenal. There are a lot of threads on our user mailing list where users praise Wicket's Ajax support. But, for every one of those threads there are at least two where users see a potential for doing something even better, so we are continuously working on improving what we already have.

What are the problems?

Igor. Transferring and injecting markup from server side into the client is not without its problems. There was very little of existing functionality out there that we can look at for inspiration, so we had to invent/roll our own implementations.

One of the interesting problems we ran into, which we have since solved, was properly supporting header contributions via Ajax, that is, a component including a script HTML tag as part of its markup response, which is received by the client as a response to XmlHttpRequest. "Header contributions" is the ability of any component or behavior in the page to contribute to the header section of the webpage, whether it is including a link to a JavaScript file or a CSS file or writing anything inline. This allows components to encapsulate their JavaScript and CSS dependencies. In order to have any kind of Ajax, you need to have some JavaScript. A component that uses Ajax and is burried somewhere deep in my page, or in some third party panel I use, can easily make sure it has any JavaScript file, such as Scriptaculous, properly referenced in the page's HTML output. Another cool thing about header contributions is that Wicket is smart enough to filter out duplicates. So if I have two of these components somewhere in my page both contribute a link to scriptaculous.js, only one link will show up in the final HTML.

Another problem is that, because we offer our users a single-threaded programming model, it is hard for us to do as many things asynchronously as we would like. So that partially takes the A out of Ajax. We are working on ways to remedy this in the coming releases. However, we still think (and majority of our users seem to agree) that not having to manually deal with threading and synchronizations issues is more then a justifiable trade off. Also, it is not that often that you need concurrent asynchronous updates in a UI.

Jonathan. Problems? Who, us?

 

 

Eelco. It has some rough edges that have to do with the fact that it is optional, and state is managed on the server side. Extensive back button support like GWT has for instance seems to be quite impossible for us.

 

What does the future look like?

Jonathan. I'd like to see Wicket do a bit better job of dealing with JavaScript fragments. Sometime back around the time Wicket Ajax support was launched (but I think after it was a bit too late), I posted a simple JavaScript object somewhere. It's purpose is simply to facilitate the programmatic construction of JavaScript in the few cases where it's needed in Wicket (you're trying to decorate an Ajax call with some special behavior rather than just doing a simple update). Other than this fairly minimal issue, things seem to be going really well so I would expect changes more in line with simple extension than architecture refactoring.

Igor. I think the developers, and our users, are very happy with Wicket's core concepts. We are currently working on tightening up our API and making it easier for our users to code against. We might also work on some higher level out of the box components - of which we already have plenty.

Eelco. I would think that Ajax stays like it is. We'll probably keep on adding neat components in the future, though we already have such a set of components that we're afraid users miss the point that one of Wicket's strongest points is that you can very easily create your own custom components. Creating your own from a good base class is often a better idea than trying to bend an existing component exactly to your needs.

Do you foresee other frameworks doing similar things in the Ajax area?

Igor. If it makes sense for them.

 

Jonathan. No idea. In general, I foresee Ajax going away and I really look forward to the day. The whole idea of doing web applications in HTML over HTTP is (of course) fundamentally flawed, even if it is still very important from a business perspective and will remain so for some time. When I first saw this general game plan for building web applications back in the mid-90's, I remember thinking "This is such a stupid plan it surely can't last long. I'll just wait for it to go away." In that context, I definitely expected Java applets and Java Web Start to take over the world. Unfortunately, Sun made a variety of mistakes (mostly in the areas of usability and platform building) and it just didn't happen, which really broke my heart because there was (and sort of still is) a real technology-driven business opportunity there you could drive a truck through. But in the end I'm certain a real and workable solution to Internet applications will come around, whether it comes from an existing player or some new upstart. In the meantime, I'll play with Wicket.

Eelco. It looks like we'll be in our own niche for a while. So many frameworks, so many choices. Though why on earth people are still using, and even creating, model 2 frameworks puzzles me!

Anything else you want to mention?

Jonathan. Nope.

 

Eelco. Thanks for the interview!

 

Igor. Thanks for the opportunity to spread the word.

 

 

Resources

AttachmentSize
jon.png2.58 KB
igor.png2.42 KB
eelco.jpg1.37 KB
ajax-classes.png54.54 KB
Published at DZone with permission of its author, Geertjan Wielenga.

Comments

Brian Diekelman replied on Sat, 2008/04/26 - 10:00pm

Wicket has been a consistent performer for me.  Both in terms of developer productivity and extensibility.

 

The ajax support works very well.  The issue I have run into on previous (pre-Wicket) projects has always been unobtrusive javascript.  I'd always find myself building the functionality twice; the first layer being just the basic webapp that works if javascript is turned off, then an 'enhanced' javascript layer on the client that interacts with a server side API.

 

Wicket handles this very well with the component model.  Every component knows how to render itself, so I just have to worry about updating that component tree and flagging components that I'd like to be redrawn on the client.  This allows me to handle the logic of the event without getting bogged down in low levels of the HTTP exchange for every form submit or link click.

Jonathan Leaver replied on Sat, 2008/04/26 - 11:25pm

Wow - fabulous interview, gentlemen!  I've been doing a lot of reading in this area lately trying to decide which framework to do my next project in - and after seeing your examples and hearing your thoughts on the design, I'm very excited to try some of this out.

Thanks for taking the time! 

Geertjan Wielenga replied on Sun, 2008/04/27 - 5:43pm

I added a list of useful resources to the end of the interview. Especially the first, to the list of Ajax/Wicket samples, is extremely helpful.

Carla Brian replied on Mon, 2012/05/21 - 5:36pm

I think there is a online tutorial for Ajax. I want to learn more on this. - Tire Works

Lucifer Williams replied on Thu, 2012/11/15 - 4:40pm

Each architecture has its advantages. GWT is probably less round-trippy and its use of air conditioning orlando client resources ought to give it certain scaling advantages. The downside of the GWT model is that you'll spend a lot more time dealing with the fact that your application is running on a client system and not on your server. Also, since Wicket doesn't push state to the client, it is secure by default and the development effort may be easier (depending on what you're doing), as your model doesn't need to be transported anywhere.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.