Статьи

Интервью: как калитка делает Аякс


Усовершенствования, которые Ajax вносит в Интернет, могут не быть вашей чашкой чая из-за JavaScript.
Либо потому, что вы находите это слишком сложным, либо потому, что вам это просто не нравится. Wicket решает эту проблему, позволяя добавлять функциональность Ajax в веб-приложения без написания одной строки JavaScript. По сути, Wicket устраняет все трудности Ajax, предоставляя все свои преимущества непосредственно разработчику Java с помощью простой модели программирования Java, полностью включающей Java, которая имеет дополнительный бонус, заключающийся в том, что вы можете инкапсулировать поведение Ajax в повторно используемые компоненты Wicket. Ниже некоторые ребята из Wicket рассказывают вам все об этом в некоторых деталях.

Всем привет! Во-первых, расскажите, пожалуйста, кто вы и какова ваша роль в проекте Wicket.

Джонатан. Привет, я Джонатан Лок. Я основал проект Wicket. Я отвечал за первоначальный дизайн и большую часть первоначальной реализации. Я также выбрал начальную команду, которая (с несколькими удачными дополнениями) все еще руководит проектом сегодня. Я был очень активен как коммиттер и в создании сообщества в течение первых двух лет, но с тех пор стал большим пользователем, очень заинтересованным наблюдателем и болельщиком.

Eelco. Здравствуй. Меня зовут Eelco Hillenius, и я участвовал в Wicket с тех пор, как Джонатан открыл его для большего количества людей в 2004 году. Я также являюсь соавтором Wicket In Action . Я работал над многими частями базы кода, как и большинство членов команды. Чем я больше всего горжусь, так это некоторыми своими идеями, такими как наследование разметки, вклады в заголовки (подробнее об этом ниже) и идея основывать нашу поддержку Ajax на поведении (которые тогда были просто модификаторами атрибутов). Без остальной команды, тем не менее, это были бы не более половины разработанных идей. Но это здорово в нашей команде; Я чувствую, что мы очень хорошо дополняем друг друга.

Игорь. Меня зовут Игорь Вайнберг. Я работаю над Wicket с конца 2005 года. Я работал во всех областях Wicket, от низкоуровневой обработки запросов до высокоуровневых компонентов, таких как DataTable. В свое время я написал первую внутреннюю реализацию Ajax от Wicket, которая с течением времени улучшилась до того уровня, которым обладает наша талантливая команда. Теперь, когда основные концепции Wicket развились до такой степени, что большинству команды это удобно, я в основном работаю над улучшением нашего API и абстракций.

Что для вас является главным обещанием, которое Ajax дает веб-приложениям?

Eelco. Насколько мне известно, в этом есть две вещи. Во-первых, это улучшенный пользовательский интерфейс, потому что обновления могут быть меньше и быстрее, и в основном они выполняются в фоновом режиме асинхронно.

Второе — улучшенная модель программирования, которую он может принести. HTTP — это протокол без сохранения состояния, который был разработан для сети взаимосвязанных документов. Он никогда не был предназначен для запуска приложений. Интересные графические интерфейсы с состоянием. Деревья, вкладки, отсортированные списки и т. Д. Хотя многие люди, вероятно, не осознают этого, разработка интересных графических интерфейсов стала намного проще с Ajax, потому что он позволяет вам снова выполнять жирное программирование с учетом состояния клиента. Интересно, что на самом деле Wicket предоставляет такую ​​же модель программирования без Ajax, но вместо этого использует некоторую память на стороне сервера.

Игорь. Это обещание более быстрых, более отзывчивых пользовательских интерфейсов. Ajax-запросы обычно несут меньшую полезную нагрузку, и, поскольку более чем один может выполняться параллельно, пользовательский интерфейс может казаться более отзывчивым для пользователя. Например, в Wicket это означает возможность визуализации только небольших поддеревьев иерархии компонентов, составляющих страницу.

Еще одним преимуществом является то, что запросы Ajax не полностью обновляют страницу, поэтому между запросами в дереве DOM на клиенте может сохраняться состояние, которое чрезвычайно хорошо масштабируется до степени сохранения состояния в веб-приложении.

Джонатан. Ajax дает более быстрые ответы для пользователей. Если бы Интернет и серверные ресурсы были быстрее, модель полностраничного обновления работала бы отлично, и никто не заботился бы об Ajax. В некотором смысле, Ajax — это временная мера, как «оптимизированное повторное отображение», которое было для редакторов на терминалах более 20 лет назад. Сегодня нас не особо волнует, насколько оптимально Eclipse рисует наш экран, потому что он настолько невероятно быстр, что на 30% лучше или хуже, вероятно, трудно даже увидеть человеческим глазом. Но поместите модем со скоростью 300 бод в середину петли дисплея, и вдруг вам будет очень интересно!

Так что Аякс не очень интересен в долгосрочной перспективе. Это там, чтобы закрыть временную дыру, и это довольно полезно для этого, по крайней мере, в настоящее время.

Как насчет тех людей, которые думают, что Ajax — грязный хак, и вам не следует так злоупотреблять Интернетом?

Eelco. Я думаю, что они должны вспомнить о том, как интернет сначала получил свой рост, захватывая телефонные линии, то, для чего они никогда не были предназначены. Ajax — не идеальное вечное решение для вещей, но на данный момент это отличный трюк, и люди наслаждаются более плавным и быстрым интерфейсом конечного пользователя и улучшенной производительностью в результате этого.

Игорь. Пока не будет другого общепринятого и доступного тонкого клиента, кроме браузера, мы будем придерживаться грязных хаков!

Это круто. Но Ajax не доставляет большого удовольствия разработчикам Java. Сначала вы должны изучить JavaScript.

Eelco. Хуже всего в JavaScript то, что он не является статически типизированным, поэтому, если вам нужно поддерживать много кода JavaScript, вам нужно быть очень дисциплинированным (и членами вашей команды), или вы окажетесь в адском обслуживании. Кроме этого, вы можете делать довольно крутые вещи. Это более мощный язык, чем думают многие.

Во всяком случае, Уикет скрывает большую часть этого для вас. Да, вы можете создавать Ajax-приложения с помощью Wicket, даже не написав ни одной строки JavaScript. Например, компонент автозаполнения, который использует Ajax для всплывающего списка вариантов в текстовом поле во время ввода, может использоваться следующим образом:

AutoCompleteTextField myField = new AutoCompleteTextField("ac", new Model("")) {
protected Iterator getChoices(String input) {
return myService.getPossibleChoices(input);
}
};

Как видите, JavaScript нет, и на самом деле он работает точно так же, как работают не-Ajax-компоненты. Тем не менее, я думаю, что действительно крутая вещь в реализации Ajax Wicket заключается в том, что вы можете инкапсулировать такое поведение в автономные компоненты. Это позволяет вам писать компоненты Ajax, которые вы можете встроить в страницу, не требуя дополнительной настройки для ее работы. Текстовое поле автозаполнения выше является хорошим примером этого.

Игорь. Изучать JavaScript не сложно, а трудно изучать FireFox JavaScript, IE6 JavaScript, IE7 JavaScript, Opera JavaScript, WebKit JavaScript и т. Д. Различия невелики, но могут вызывать огромные зависания и очень раздражают разработчиков Java, которые привыкли к Java быть намного более последовательным. Еще одной проблемой является отсутствие действительно хорошего отладчика JavaScript, который Java-разработчики считают само собой разумеющимся.

Приятной особенностью поддержки Ajax от Wicket является то, что мы прошли через эту боль и создали JavaScript, который работает во всех основных браузерах, поэтому нашим пользователям это не нужно. С помощью нескольких строк кода Java вы можете подключить событие JavaScript, такое как «onclick» или «onchange», к обратному вызову на стороне сервера, который, в свою очередь, может обновить одну или несколько частей дерева DOM клиента с новой разметкой. Например, мы можем легко заменить существующий компонент Link, который генерирует нормальный обратный вызов на стороне сервера, компонентом AjaxFallbackLink, который использует Ajax, когда он доступен, но постепенно снижается до обычного обратного вызова на стороне сервера, когда Ajax недоступен, и все без пользователь должен сделать что-нибудь.

Например, если мы возьмем вариант использования таблицы, показывающей список пользователей, обычная ссылка для удаления пользователя может быть реализована следующим образом:

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
}
}

Вот чистая версия Ajax:

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);
}
}

А вот запасная версия:

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
}
}
}

Все блага Ajax без линии JavaScript. Вот еще один пример: предположим, у меня есть два DropDownChoices (поля выбора) на странице, чьи модели связаны так, что выбор в первом диктует параметры, доступные во втором (это обычно называется «связанные блоки выбора»). Предположим также, что теперь я хочу обновить окна выбора через Ajax, все что мне нужно сделать в Wicket:

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);
}
});
}

Этот пример доступен в прямом эфире здесь . Как видите, я создал два связанных блока выбора, которые обновляются через Ajax, без написания Javascript или каких-либо знаний о том, как Ajax работает в браузере.

Джонатан.
Я могу быть худшим в мире JavaScript-кодером.
Я едва знаю строку JavaScript и обычно могу найти способ испортить несколько строк, которые я пишу. Я, вероятно, вообще не смог бы работать с Ajax без простой модели программирования на Java для Ajax.

Но разве GWT не делает что-то подобное тоже? Какая разница и почему?

Игорь. GWT создает толстый клиент, который использует браузер в качестве среды выполнения. Wicket создает традиционное веб-приложение для тонких клиентов, которое работает на сервере. Примером преимущества толстых клиентов является то, что они могут использовать ресурсы клиентского ПК, на которых они работают (например, память для хранения состояния), и, таким образом, значительно лучше масштабироваться для чрезвычайно большого числа пользователей. Примером преимущества тонких клиентов является то, что обычно хранилище данных, поддерживающее приложение, находится на очень быстром локальном соединении, и, следовательно, приложениям тонких клиентов не требуется так много оптимизации запросов, и они значительно упрощают использование локальных данных и кэширования для конкретных пользователей.

Джонатан. В моем ограниченном понимании, GWT просто решает проблему, отличную от Wicket. Похоже, что GWT ориентирован на приложения, размещенные в браузерах, а Wicket — это традиционная серверная веб-платформа. У каждой архитектуры есть свои преимущества. GWT, вероятно, менее цикличен, и его использование клиентских ресурсов должно дать ему определенные преимущества масштабирования. Недостатком модели GWT является то, что вы будете тратить гораздо больше времени на то, чтобы ваше приложение работало на клиентской системе, а не на вашем сервере. Кроме того, поскольку Wicket не передает состояние клиенту, по умолчанию он безопасен, и процесс разработки может быть проще (в зависимости от того, что вы делаете), поскольку вашу модель не нужно никуда переносить.

Eelco. GWT — это совсем другая структура. Wicket по-прежнему предполагает, что вы хотите создать хотя бы часть своего приложения «старомодным» способом, чтобы оно работало без JavaScript, появлялось в поисковых системах, могло быть добавлено в закладки и т. Д. GWT создает нечто, более похожее на апплеты ; независимые приложения, которые размещаются на веб-страницах.

Есть ли другие типичные проблемы, связанные с Ajax, с которыми сталкивается Wicket?

Джонатан. Как указывал Игорь выше, у Wicket есть очень умный набор «запасных» компонентов, которые являются Ajaxy, когда браузер поддерживает JavaScript, но возвращаются к полному обновлению страницы, когда JavaScript отсутствует. Это невероятно полезно.

 

Игорь. Wicket заботится о том, чтобы пользователи могли маршалировать и демаршировать данные между сервером и браузером, обходя проблему. Вместо отправки данных клиенту Wicket визуализирует компоненты на стороне сервера и отправляет визуализированную разметку. Это может быть не так эффективно, но, несомненно, значительно упрощает и ускоряет разработку адаптированного поведения. Например, если кто-то хочет обновить панель, которая показывает пользовательскую информацию о клиенте через Ajax, все, что нужно, это сообщить Wicket, что панель должна быть обновлена. Нет никакого маршаллинга объекта User в представление JSON, и нет демаршаллинга его на клиенте, и нет кода для манипулирования DOM на клиенте.

Как все это работает под капотом? Где-то должен быть Javascript, пусть даже под капотом.

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.

Другая проблема состоит в том, что, поскольку мы предлагаем нашим пользователям однопотоковую модель программирования, нам трудно делать столько вещей асинхронно, сколько мы хотели бы. Так что это частично забирает А из Аякса. Мы работаем над тем, чтобы исправить это в следующих выпусках. Тем не менее, мы все еще думаем (и большинство наших пользователей, похоже, с этим согласны), что отсутствие необходимости вручную решать проблемы с потоками и синхронизацией является более чем оправданным компромиссом. Кроме того, не так часто требуется одновременное асинхронное обновление в пользовательском интерфейсе.

Джонатан. Проблемы? Кто мы?

 

 

Eelco. У этого есть некоторые грубые края, которые имеют отношение к факту, что это является дополнительным, и состояние управляется на стороне сервера. Широкая поддержка кнопок «назад», как, например, у GWT, кажется для нас совершенно невозможной.

 

Как выглядит будущее?

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