SlideShare une entreprise Scribd logo
1  sur  147
Télécharger pour lire hors ligne
APACHE WICKET 
Apache Wicket 
10 years and beyond 
Martijn Dashorst 
topicus onderwijs 
@dashorst
a brief history 
of Wicket 
the current state 
of Wicket 
the future 
of Wicket
co-author
10 year contributor to Wicket
started in 2004 at topicus 
without any knowledge of web programming
before Wicket 
at topicus
2004
using maverick velocity 
hibernate jasperreports
lots of XML configuration
1 change requires N files to be 
modified 
(for large values of N) 
<command name="admin.tabelbeheer.edittoetsonderdeel"> 
<controller class="nl.topicus.bao.web.ctrl.lab.toetsen. 
<view name="success" path="/admin/tabelbeheer/toetsen/e 
<transform path="/mlayout/mainlayout.vm"> 
<param name="_pagetitle" value="Beheer Tabellen 
</transform> 
</view> 
<view name="error" path="/admin/tabelbeheer/toetsen/edi 
<transform path="/mlayout/mainlayout.vm"> 
<param name="_pagetitle" value="Beheer Tabellen 
</transform> 
</view> 
<view name="list" path="admin.tabelbeheer.edittoets.m" 
</command>
high learning curve
no back button support 
no multi-tab support
HTTP Session dumping 
ground
little to no reuse 
</tr> 
#if($model.bean.absentieRegels.empty) 
<tr> 
<td colspan="19" class="border-r">#formname('groep.absent' 
</tr> 
#else 
#set($columnIndexes=[1,2,3,4,5,6,7,8,9,10]) 
#foreach($row in $model.bean.absentieRegels) 
<tr> 
<td class="columnvalue">$arrayTool.elementAt($row, 0)</td 
#foreach($index in $columnIndexes) 
#set($melding=$arrayTool.elementAt($row, $index))
complex UI neigh impossible
a framework that makes 
reuse possible, minimises 
configuration, server side 
state management easy 
and is as type safe as 
possible
Action Framework Anvil Apache Click Apache MyFaces Apache 
Shale Apache Sling Apache Struts Apache Struts 2 Apache 
Tapestry Apache Turbine Apache Wicket AppFuse Aranea Web 
Framework AribaWeb Aurora Baritus Barracuda Bento Bishop Brill 
Calyxo Cameleon Canyamo Caramba Cassandra Chiba Chrysalis 
Dinamica Dovetail DWR Echo Eclipse RAP Expresso fleXive Flower 
framework Folium FormEngine Genie Grails GWT Hamlets Helma 
Induction ItsNat Jacquard Jaffa Japple JAT JATO JBanana JBoss 
Seam Jeenius JFormular JOSSO JPublish JSPWidget Jspx-bay 
jStatemachine Jucas JVx JWAA JWarp jWic jZeno jZonic Macaw 
Makumba Maverick Melati Mentawai Millstone Nacho Niggle 
OpenEmcee OpenLaszlo OpenXava Oracle ADF OXF Pandora 
Playframework Pustefix Restlet RIFE Roma Meta Framework RSF 
Scope SerfJ Shocks Smile SOFIA Sombrero Spark Spring MVC 
Strecks Stripes Swinglets SwingWeb Tapestry TeaServlet ThinWire 
Trimpath Junction Turbine Vaadin Verge VRaptor Vroom Warfare 
Wavemaker WebObjects WebOnSwing WebWork wingS Xoplon Ze 
Framework ZK ztemplates
120+ java web frameworks
18 August 2004
public class EditPage extends WebPage { 
private Person person; 
public EditPage(Person person) { 
this.person = person; 
add(new Button("save") { 
@Override 
public void onSubmit() { 
Entities.save(person); 
setResponsePage(new ShowPage(person)); 
} 
}); 
} 
}
a framework that makes 
reuse possible, minimises 
configuration, server side 
state management easy 
and is as type safe as 
possible 
✓ ✓ 
✓ 
✓
Action Framework Anvil Apache Click Apache MyFaces Apache 
Shale Apache Sling Apache Struts Apache Struts 2 Apache 
Tapestry Apache Turbine Apache Wicket AppFuse Aranea Web 
Framework AribaWeb Aurora Baritus Barracuda Bento Bishop Brill 
Calyxo Cameleon Canyamo Caramba Cassandra Chiba Chrysalis 
Dinamica Dovetail DWR Echo Eclipse RAP Expresso fleXive Flower 
framework Folium FormEngine Genie Grails GWT Hamlets Helma 
Induction ItsNat Jacquard Jaffa Japple JAT JATO JBanana JBoss 
Seam Jeenius JFormular JOSSO JPublish JSPWidget Jspx-bay 
jStatemachine Jucas JVx JWAA JWarp jWic jZeno jZonic Macaw 
Makumba Maverick Melati Mentawai Millstone Nacho Niggle 
OpenEmcee OpenLaszlo OpenXava Oracle ADF OXF Pandora 
Playframework Pustefix Restlet RIFE Roma Meta Framework RSF 
Scope SerfJ Shocks Smile SOFIA Sombrero Spark Spring MVC 
Strecks Stripes Swinglets SwingWeb Tapestry TeaServlet ThinWire 
Trimpath Junction Turbine Vaadin Verge VRaptor Vroom Warfare 
Wavemaker WebObjects WebOnSwing WebWork wingS Xoplon Ze 
Framework ZK ztemplates
Action Framework Anvil Apache Click Apache MyFaces Apache 
Shale Apache Sling Apache Struts Apache Struts 2 Apache 
Tapestry Apache Turbine Apache Wicket AppFuse Aranea Web 
Framework AribaWeb Aurora Baritus Barracuda Bento Bishop Brill 
Calyxo Cameleon Canyamo Caramba Cassandra Chiba Chrysalis 
Dinamica Dovetail DWR Echo Eclipse RAP Expresso fleXive Flower 
framework Folium FormEngine Genie Grails GWT Hamlets Helma 
Induction ItsNat Jacquard Jaffa Japple JAT JATO JBanana JBoss 
Seam Jeenius JFormular JOSSO JPublish JSPWidget Jspx-bay 
jStatemachine Jucas JVx JWAA JWarp jWic jZeno jZonic Macaw 
Makumba Maverick Melati Mentawai Millstone Nacho Niggle 
OpenEmcee OpenLaszlo OpenXava Oracle ADF OXF Pandora 
Playframework Pustefix Restlet RIFE Roma Meta Framework RSF 
Scope SerfJ Shocks Smile SOFIA Sombrero Spark Spring MVC 
Strecks Stripes Swinglets SwingWeb Tapestry TeaServlet ThinWire 
Trimpath Junction Turbine Vaadin Verge VRaptor Vroom Warfare 
Wavemaker WebObjects WebOnSwing WebWork wingS Xoplon Ze 
Framework ZK ztemplates
15 java web frameworks alive 
i.e. made any release in the last year
including Wicket!
What is Wicket? 
Apache Wicket 
From Wikipedia, the free encyclopedia 
Apache Wicket, commonly referred to as 
Wicket, is a lightweight component-based web 
application framework for the Java programming 
language conceptually similar to JavaServer 
Faces and Tapestry. It was originally written by 
Jonathan Locke in April 2004. Version 1.0 was 
released in June 2005. It graduated into an 
Apache top-level project in June 2007.[2]
A brief history of Wicket
2004
2004 
The Server Side
2004 2005 
codehaus.org 
The Server Side
2004 2005 
codehaus.org 
The Server Side
2004 
codehaus.org 
1.0 
1.1 
The Server Side JavaOne 
2006 
1.2 
2005 
AJAX
2007
2007 
2008 
1.3
2007 
2008 2009 
1.3 
1.4 
2010 2011 
1.5
2007 
2008 2009 
1.3 
1.4 
2010 2011 
1.5
2012 
6.0 
2013 2014 
6.10 
6.14 
6.12 
6.2 
6.4 
6.6 
6.8 
6.1 6.5 6.9 
6.13 
6.11 
7.0.0-M4 
6.18 
7.0.0-M2 
6.16 
6.15 
7.0.0-M1 
6.3 6.7 
6.17 
7.0.0-M3
That's 
of Apache Wicket! 10 years
The state of Wicket
1. core 
2. extensions 
3. spring 
4. datetime 
5. auth-roles
Mailinglist traffic
Commit activity
User Manual 
195 
25 Wicket Internals 
25.1 Page storing 
During request handling, Wicket manages page instances through interface 
org.apache.wicket.request.handler.IPageProvider. This interface creates a new page instance or 
loads a previously serialized page instance if we provide the corrisponding page id. IPageProvider delegates 
page creation and retrieval to interface org.apache.wicket.request.mapper.IPageSource. When page 
class is provided IPageSource delegates page creation to interface org.apache.wicket.IPageFactory, 
while when page id is provided it uses interface org.apache.wicket.page.IPageManager to load the 
previously serialized page. 
The following workflow diagram summarizes the mechanism seen so far: 
IPageManager 
org.apache.wicket.page.IPageManager's task is to manage which pages have been used in a request 
and store their last state in the backing stores, namely IPageStore. The default implementation 
org.apache.wicket.page.PageStoreManager collects all stateful pages which have been used in the 
request cycle (more than one page can be used in a single request if for example setResponsePage() or 
RestartResponseException is used). At the end of the request all collected page instances are being stored 
in the first level cache - http session. They are stored in http session attribute named 
"wicket:persistentPageManagerData-APPLICATION_NAME" and passed to the underlying IPageStore 
. When the next http request comes IPageProvider will ask for page with specific id and PageStoreManager 
will look first in the http session and if no match is found then it will delegate to the IPageStore. At the end of the 
second request the http session based cache is being overwritten completely with the newly used page 
instances. 
To setup another IPageManager implementat ion use 
org.apache.wicket.Application.setPageManagerProvider(IPageManagerProvider). The 
custom IPageManager implementation may or may not use IPageStore/IDataStore. 
IPageStore 
org.apache.wicket.pageStore.IPageStore's role is to mediate the storing and loading of pages done by 
the under lying IDataStore. The defaul t implementat ion 
org.apache.wicket.pageStore.DefaultPageStore pre-processes the pages before passing them to 
As you can see above, the Exception gets raised during the initialization of the WicketTester instance even 
before the actual test method gets executed. Even though we have applied rather cool and simple annotation 
based test configuration already described and passed in perfectly well prepared ApplicationContext instance to 
the WicketTester instance in the constructor, somewhere down the rabbit hole someone complained that no 
WebApplicationContext instance could have been found which seems to be required in order to initialize the 
WicketTester properly. 
The problem that we run against here is due to the fact that SpringComponentInjector during its own initialization 
is trying to get hold of an according Spring's ApplicationContext instance that would normally be there in a 
runtime environment but does not find any since we are running in a test environment currently. 
SpringComponentInjector delegates to Spring's own WebApplicationContextUtils class to retrieve the instance of 
ApplicationContext out of the ServletContext which is perfectly fine for a runtime environment but is unfortunately 
failing in a test environment: 
183 
public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc) 
throws IllegalStateException { 
WebApplicationContext wac = getWebApplicationContext(sc); 
if (wac == null) { 
throw new IllegalStateException("No WebApplicationContext found: no 
ContextLoaderListener registered?"); 
} 
return wac; 
} 
If you still remember we defined a ContextLoaderListener in our web.xml file as part of the configuration of our 
runtime environment that makes sure an according WebApplicationContext instance gets initialized and 
registered against the ServletContext properly. Luckily, this problem can easily be solved if we slightly change 
the way we initialize SpringComponentInjector in our main MyWebApplication class. Apart from the constructor 
that we have used so far, there is another constructor in the SpringComponentInjector class that expects the 
caller to provide it with an according ApplicationContext instance rather than trying to resolve one on its own: 
public SpringComponentInjector(WebApplication webapp, ApplicationContext ctx, 
boolean wrapInProxies) 
{ 
if (webapp == null) 
{ 
throw new IllegalArgumentException("Argument [[webapp]] cannot be null"); 
} 
if (ctx == null) 
{ 
throw new IllegalArgumentException("Argument [[ctx]] cannot be null"); 
} 
// store context in application's metadata … 
webapp.setMetaData(CONTEXT_KEY, new ApplicationContextHolder(ctx)); 
// … and create and register the annotation aware injector 
InjectorHolder.setInjector(new AnnotSpringInjector(new ContextLocator(),
In a Nutshell, Wicket... 
…has had 18,255 commits made by 62 contributors 
representing 318,037 lines of code 
…is mostly written in Java with 
a well-commented source code 
…has a well established, mature codebase maintained 
by a large development team with stable Y-O-Y 
commits 
…took an estimated 84 years of effort (COCOMO model) 
starting with its first commit in September, 2004 
ending with its most recent commit 1 days ago 
– openhub.net report for Wicket
The future of Wicket
Wicket 1.4 
security releases only
Wicket 1.5 
security releases only
Wicket 6
java 6
semantic 
versioning
semi-monthly releases 
mainly bug fixes 
some new minor features
Wicket 7
Java 7
Servlet 3
Minor API breaks
Component queuing
public class HomePage extends WebPage { 
public HomePage() { 
add(new Label("title", "Hello!")); 
} 
}
public class HomePage extends WebPage { 
public HomePage() { 
add(new Label("title", "Hello!")); 
} 
} <html> 
<body> 
<h1 wicket:id="title"></h1> 
</body> 
</html>
public class HomePage extends WebPage { 
public HomePage() { 
add(new Label("title", "Hello!")); 
} 
} <html> 
<body> 
<h1 wicket:id="title"></h1> 
</body> 
</html>
Add a <div> around content...
<html> 
<body> 
<div wicket:id="container"> 
<h1 wicket:id="title"></h1> 
</div> 
</body> 
</html>
<html> 
<body> 
<div wicket:id="container"> 
<h1 wicket:id="title"></h1> 
</div> 
</body> 
</html> public class HomePage extends WebPage { 
public HomePage() { 
add(new WebMarkupContainer("container")); 
add(new Label("title", "Hello!")); 
} 
}
<html> 
<body> 
<div wicket:id="container"> 
<h1 wicket:id="title"></h1> 
</div> 
</body> 
</html> public class HomePage extends WebPage { 
public HomePage() { 
add(new WebMarkupContainer("container")); 
add(new Label("title", "Hello!")); 
} 
}
in Wicket 
code always follows markup
<html> 
<body> 
<div wicket:id="container"> 
<h1 wicket:id="title"></h1> 
</div> 
</body> 
</html>
<html> 
<body> 
<div wicket:id="container"> 
<h1 wicket:id="title"></h1> 
</div> 
</body> 
</html> 
public class HomePage extends WebPage { 
public HomePage() { 
WebMarkupContainer container = 
new WebMarkupContainer("container"); 
add(container); 
add(new Label("title", "Hello!")); 
} 
}
<html> 
<body> 
<div wicket:id="container"> 
<h1 wicket:id="title"></h1> 
</div> 
</body> 
</html> 
public class HomePage extends WebPage { 
public HomePage() { 
WebMarkupContainer container = 
new WebMarkupContainer("container"); 
add(container); 
add(new Label("title", "Hello!")); 
} 
}
<html> 
<body> 
<div wicket:id="container"> 
<h1 wicket:id="title"></h1> 
</div> 
</body> 
</html> 
public class HomePage extends WebPage { 
public HomePage() { 
WebMarkupContainer container = 
new WebMarkupContainer("container"); 
add(container); 
container.add(new Label("title", "Hello!")); 
} 
}
in Wicket 
or does it? 
code always follows markup
Enter Component Queuing 
(coming to you in wicket 7)
What if we delay adding 
components? 
Queue components until their location 
in the markup hierarchy is know 
markupContainer.add(new Label(...)); 
markupContainer.queue(new Label(...));
public class HomePage extends WebPage { 
public HomePage() { 
WebMarkupContainer container = 
new WebMarkupContainer("container"); 
add(container); 
container.add(new Label("title", "Hello!")); 
} 
} 
public class HomePage extends WebPage { 
public HomePage() { 
queue(new WebMarkupContainer("container")); 
queue(new Label("title", "Hello!")); 
} 
}
<html> 
<body> 
<div wicket:id="container"> 
<html> 
<body> 
<header><h1 wicket:id="title"></h1></header> 
<div wicket:id="container"> 
... 
</div> 
</body> 
</html> 
<h1 wicket:id="title"></h1> 
</div> 
</body> 
</html>
Limitations of 
Component Queuing
queue(new Label("label", "Some text")); 
queue(new Label("label", "Other text"));
queue(new Label("label", "Some text")); 
queue(new Label("label", "Other text"));
Restrictions of Queuing: Ancestors 
queue(new Label("first")); 
queue(new Label("last")); 
WebMarkupContainer secure=new 
WebMarkupContainer("secure") { 
public void onConfigure() { 
super.onConfigure(); 
setVisible(isViewingOwnProfile()); 
} 
}; 
queue(secure); 
secure.queue(new Label("creditCardNumber")); 
secure.queue(new Label("creditCardExpiry"));
<h3> 
Welcome, 
<span wicket:id="first"></span> 
<span wicket:id="last"></span>! 
</h3> 
<fieldset wicket:id="secure"> 
<legend>Secure</legend> 
<dt>Card expiry: <i wicket:id="creditCardExpiry"> 
<dt>Card number: <i wicket:id="creditCardNumber"> 
</fieldset>
<h3> 
Welcome, 
<span wicket:id="first"></span> 
<span wicket:id="last"></span>! 
</h3> 
<fieldset wicket:id="secure"> 
<legend>Secure</legend> 
<dt>Card expiry: <i wicket:id="creditCardExpiry"> 
<dt>Card number: <i wicket:id="creditCardNumber"> 
</fieldset>
<h3> 
Welcome, 
<span wicket:id="first"></span> 
<span wicket:id="last"></span>! 
</h3> 
<fieldset wicket:id="secure"> 
<legend>Secure</legend> 
<dt>Card expiry: <i wicket:id="creditCardExpiry"> 
</fieldset> 
<dt>Card number: <i wicket:id="creditCardNumber">
<h3> 
Welcome, 
<span wicket:id="first"></span> 
<span wicket:id="last"></span>! 
</h3> 
<fieldset wicket:id="secure"> 
<legend>Secure</legend> 
<dt>Card expiry: <i wicket:id="creditCardExpiry"> 
</fieldset> 
<dt>Card number: <i wicket:id="creditCardNumber">
<fieldset wicket:id="secure"> 
<h3> 
Welcome, 
<span wicket:id="first"></span> 
<span wicket:id="last"></span>! 
</h3> 
<legend>Secure</legend> 
<dt>Card expiry: <i wicket:id="creditCardExpiry"> 
<dt>Card number: <i wicket:id="creditCardNumber"> 
</fieldset>
<fieldset wicket:id="secure"> 
<h3> 
Welcome, 
<span wicket:id="first"></span> 
<span wicket:id="last"></span>! 
</h3> 
<legend>Secure</legend> 
<dt>Card expiry: <i wicket:id="creditCardExpiry"> 
<dt>Card number: <i wicket:id="creditCardNumber"> 
</fieldset>
Component Queuing 
• Wicket 7 feature 
• Prefer queue() when markup hierarchy can be altered 
• Uniqueness of Wicket IDs still requirement at same 
level of queuing 
• Can move down into child markup hierarchy 
• Can't move up the markup hierarchy
Wicket 8
Java 8
PROJECT LAMBDA 
“functional” programming in 
Java
public interface ILinkListener { 
void onLickClicked(); 
} 
ILinkListener l = new ILinkListener(){ 
@Override 
public void onLinkClicked() { 
System.out.println("Klik"); 
} 
}
public interface ILinkListener { 
void onLickClicked(); 
} 
ILinkListener l = () -> { 
System.out.println("Klik"); 
}
ILinkListener l = new ILinkListener(){ 
ILinkListener l = () -> { 
System.out.println("Klik"); 
} 
@Override 
public void onLinkClicked() { 
System.out.println("Klik"); 
} 
} 
or
add(new Link<Void>("save") { 
@Override 
public void onClick() { 
dao.save(object); 
getSession().info("Saved."); 
setResponsePage(new OtherPage()) 
} 
});
add(new Link<Void>("save") { 
@Override 
public void onClick() { 
dao.save(object); 
getSession().info("Saved."); 
setResponsePage(new OtherPage()) 
} 
});
add(new Link<>("save").onClick(()-> { 
dao.save(object); 
getSession().info("Saved."); 
setResponsePage(new OtherPage()) 
}); 
no more type 
information
private void onSave() { 
dao.save(object); 
getSession().info("Saved."); 
setResponsePage(new OtherPage()) 
}
private void onSave() { 
dao.save(object); 
getSession().info("Saved."); 
setResponsePage(new OtherPage()) 
} 
add(new Link<Void>("save") 
.onClick(this::onSave));
A link with onclick, visibility and 
body
add(new Link<Void>("like"));
add(new Link<Void>("like") { 
});
add(new Link<Void>("like") { 
@Override 
public void onClick() { 
person.likedBy(me); 
} 
});
add(new Link<Void>("like") { 
@Override 
public void onClick() { 
person.likedBy(me); 
} 
@Override 
public boolean isVisible() { 
return person.isNotLiked(); 
} 
});
add(new Link<Void>("like") { 
@Override 
public void onClick() { 
person.likedBy(me); 
} 
@Override 
public boolean isVisible() { 
return person.isNotLiked(); 
} 
}.setBody());
add(new Link<Void>("like") { 
@Override 
public void onClick() { 
person.likedBy(me); 
} 
@Override 
public boolean isVisible() { 
return person.isNotLiked(); 
} 
}.setBody(new AbstractReadOnlyModel<String>() { 
}));
add(new Link<Void>("like") { 
@Override 
public void onClick() { 
person.likedBy(me); 
} 
@Override 
public boolean isVisible() { 
return person.isNotLiked(); 
} 
}.setBody(new AbstractReadOnlyModel<String>() { 
@Override 
public String getObject() { 
} 
}));
add(new Link<Void>("like") { 
@Override 
public void onClick() { 
person.likedBy(me); 
} 
@Override 
public boolean isVisible() { 
return person.isNotLiked(); 
} 
}.setBody(new AbstractReadOnlyModel<String>() { 
@Override 
public String getObject() { 
StringBuilder sb = new StringBuilder("Like "); 
sb.append(person.getFirstName()); 
return sb.toString(); 
} 
}));
A link with onclick, visibility and 
body
add(new Link<>("like"));
add(new Link<>("like") 
);
add(new Link<>("like") 
.visible(() -> person.isNotLiked()) 
);
add(new Link<>("like") 
.visible(() -> person.isNotLiked()) 
.onClick(() -> person.likedBy(me)) 
);
add(new Link<>("like") 
.visible(() -> person.isNotLiked()) 
.onClick(() -> person.likedBy(me)) 
.body(() -> { 
}) 
);
add(new Link<>("like") 
.visible(() -> person.isNotLiked()) 
.onClick(() -> person.likedBy(me)) 
.body(() -> { 
StringBuilder sb = new StringBuilder("Like "); 
sb.append(person.getFirstName()); 
return sb.toString(); 
}) 
);
add(new Link<>("like") 
.visible(() -> person.isNotLiked()) 
.onClick(() -> person.likedBy(me)) 
.body(() -> { 
StringBuilder sb = new StringBuilder("Like "); 
sb.append(person.getFirstName()); 
return sb.toString(); 
}) 
); 
add(new Link<Void>("like") { 
@Override 
public void onClick() { 
person.likedBy(me); 
} 
@Override 
public boolean isVisible() { 
return person.isNotLiked(); 
} 
}.setBody(new AbstractReadOnlyModel<String>() { 
@Override 
public String getObject() { 
StringBuilder sb = new StringBuilder("Like "); 
sb.append(person.getFirstName()); 
return sb.toString(); 
} 
})); 
Anon inner classes: 17 lines 
Java 8 lambdas: 9 lines
nashorn
JavaScript validation
ScriptEngineManager m 
= new ScriptEngineManager(); 
ScriptEngine nashorn 
= m.getEngineByName("nashorn"); 
nashorn.put("age", validatable.getValue()); 
String js = "age >= 18"; 
try { 
Object result = nashorn.eval(js); 
if(!((Boolean)result) { 
ValidationError e = new ValidationError(); 
validatable.error(e); 
} 
} catch(Exception e) { 
}
ScriptEngineManager m 
= new ScriptEngineManager(); 
ScriptEngine nashorn 
= m.getEngineByName("nashorn"); 
nashorn.put("age", validatable.getValue()); 
String js = "age >= 18"; 
try { 
Object result = nashorn.eval(js); 
if(!((Boolean)result) { 
ValidationError e = new ValidationError(); 
validatable.error(e); 
} 
} catch(Exception e) { 
}
ScriptEngineManager m 
= new ScriptEngineManager(); 
ScriptEngine nashorn 
= m.getEngineByName("nashorn"); 
nashorn.put("age", validatable.getValue()); 
String js = "age >= 18"; 
try { 
Object result = nashorn.eval(js); 
if(!((Boolean)result) { 
ValidationError e = new ValidationError(); 
validatable.error(e); 
} 
} catch(Exception e) { 
}
ScriptEngineManager m 
= new ScriptEngineManager(); 
ScriptEngine nashorn 
= m.getEngineByName("nashorn"); 
nashorn.put("age", validatable.getValue()); 
String js = "age >= 18"; 
try { 
Object result = nashorn.eval(js); 
if(!((Boolean)result) { 
ValidationError e = new ValidationError(); 
validatable.error(e); 
} 
} catch(Exception e) { 
}
ScriptEngineManager m 
= new ScriptEngineManager(); 
ScriptEngine nashorn 
= m.getEngineByName("nashorn"); 
nashorn.put("age", validatable.getValue()); 
String js = "age >= 18"; 
Object result = nashorn.eval(js); 
try { 
if(!((Boolean)result) { 
ValidationError e = new ValidationError(); 
validatable.error(e); 
} 
} catch(Exception e) { 
}
ScriptEngineManager m 
= new ScriptEngineManager(); 
ScriptEngine nashorn 
= m.getEngineByName("nashorn"); 
nashorn.put("age", validatable.getValue()); 
String js = "age >= 18"; 
Object result = nashorn.eval(js); 
if(!((Boolean)result) { 
ValidationError e = new ValidationError(); 
validatable.error(e); 
} 
try { 
} catch(Exception e) { 
}
ScriptEngineManager m 
= new ScriptEngineManager(); 
ScriptEngine nashorn 
= m.getEngineByName("nashorn"); 
nashorn.put("age", validatable.getValue()); 
String js = "age >= 18"; 
try { 
Object result = nashorn.eval(js); 
if(!((Boolean)result) { 
ValidationError e = new ValidationError(); 
validatable.error(e); 
} 
} catch (Exception e) { 
}
java.time
Roadmap
Monthly releases
feb mar nov 
6.14 
6.15 
7.0-M1 
7.0-M2 
6.18 
7.0-M4 
2014 
jan 
6.19 
7.0-RC
feb mar may 
7.0? 
7.1? 
7.5? 
8.0-M1? 
2015 
jun 
7.6? 
8.0-M2?
Is there a future for 
server-side frameworks?
“We continue to see teams run into trouble using 
JSF -- JavaServer Faces -- and are recommending 
you avoid this technology.” 
–ThoughtWorks Technology Radar January 2014
“We continue to see teams run into trouble using 
JSF -- JavaServer Faces -- and are recommending 
you avoid this technology. Teams seem to choose 
JSF because it is a J2EE standard without really 
evaluating whether the programming model suits 
them. We think JSF is flawed because it tries to 
abstract away HTML, CSS and HTTP, exactly the 
reverse of what modern web frameworks do. JSF, 
like ASP.NET webforms, attempts to create 
statefulness on top of the stateless protocol HTTP 
and ends up causing a whole host of problems 
involving shared server-side state. We are aware 
of the improvements in JSF 2.0, but think the 
model is fundamentally broken. We recommend 
teams use simple frameworks and embrace and 
understand web technologies including HTTP, 
HTML and CSS.” 
–ThoughtWorks Technology Radar January 2014
“We continue to see teams run into trouble using 
JSF and are recommending you avoid this 
technology. We think JSF is flawed because it tries 
to abstract away HTML, CSS and HTTP. JSF, like 
ASP.NET webforms, attempts to create 
statefulness on top of the stateless protocol HTTP. 
We think the model is fundamentally broken.” 
–ThoughtWorks Technology Radar January 2014
“We continue to see teams run into trouble using 
JSF and are recommending you avoid this 
technology. We think JSF is flawed because it tries 
to abstract away HTML, CSS and HTTP. JSF, like 
ASP.NET webforms, attempts to create 
statefulness on top of the stateless protocol HTTP. 
We think the model is fundamentally broken.” 
–ThoughtWorks Technology Radar January 2014
“We recommend teams use simple 
frameworks and embrace and 
understand web technologies 
including HTTP, HTML and CSS.”
JavaScript Frameworks War 
JQuery AngularJS Ember.js React 
Backbone.js Meteor KnockoutJS Dojo 
Agility.js CanJS Polymer Mithril 
Ampersand Maria Flight Knockback.js
What is the Future for web 
development?
What is the Future for web 
development? 
Web Components
What is the Future for web 
development? 
Web Components 
AngularJS Polymer 
(2.0)
What is the Future of Wicket?
a brief history 
of Wicket 
the current state 
of Wicket 
the future 
of Wicket 
Summary
Thank you!
Questions?
contact 
@dashorst 
topicus stand

Contenu connexe

Tendances

Spring Booted, But... @JCConf 16', Taiwan
Spring Booted, But... @JCConf 16', TaiwanSpring Booted, But... @JCConf 16', Taiwan
Spring Booted, But... @JCConf 16', TaiwanPei-Tang Huang
 
Introduction to Apache Roller
Introduction to Apache RollerIntroduction to Apache Roller
Introduction to Apache RollerMatt Raible
 
Spring Boot & WebSocket
Spring Boot & WebSocketSpring Boot & WebSocket
Spring Boot & WebSocketMing-Ying Wu
 
Reactive microservices with Micronaut - GR8Conf EU 2018
Reactive microservices with Micronaut - GR8Conf EU 2018Reactive microservices with Micronaut - GR8Conf EU 2018
Reactive microservices with Micronaut - GR8Conf EU 2018Alvaro Sanchez-Mariscal
 
Microservices with Spring Boot
Microservices with Spring BootMicroservices with Spring Boot
Microservices with Spring BootJoshua Long
 
Apache Camel - FUSE community day London 2010 presentation
Apache Camel - FUSE community day London 2010 presentationApache Camel - FUSE community day London 2010 presentation
Apache Camel - FUSE community day London 2010 presentationClaus Ibsen
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkBo-Yi Wu
 
A Tour of Wyriki
A Tour of WyrikiA Tour of Wyriki
A Tour of WyrikiMark Menard
 
Deploying to azure web sites
Deploying to azure web sitesDeploying to azure web sites
Deploying to azure web sitesGiant Penguin
 
HTTP, JSON, JavaScript, Map&Reduce built-in to MySQL
HTTP, JSON, JavaScript, Map&Reduce built-in to MySQLHTTP, JSON, JavaScript, Map&Reduce built-in to MySQL
HTTP, JSON, JavaScript, Map&Reduce built-in to MySQLUlf Wendel
 
Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...
Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...
Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...Alexander Lisachenko
 
Architecting Large Enterprise Java Projects
Architecting Large Enterprise Java ProjectsArchitecting Large Enterprise Java Projects
Architecting Large Enterprise Java ProjectsMarkus Eisele
 
Red Hat and Oracle: Delivering on the Promise of Interoperability in Java EE 7
Red Hat and Oracle: Delivering on the Promise of Interoperability in Java EE 7Red Hat and Oracle: Delivering on the Promise of Interoperability in Java EE 7
Red Hat and Oracle: Delivering on the Promise of Interoperability in Java EE 7Max Andersen
 
Webpack Encore Symfony Live 2017 San Francisco
Webpack Encore Symfony Live 2017 San FranciscoWebpack Encore Symfony Live 2017 San Francisco
Webpack Encore Symfony Live 2017 San FranciscoRyan Weaver
 
High Performance JavaScript - jQuery Conference SF Bay Area 2010
High Performance JavaScript - jQuery Conference SF Bay Area 2010High Performance JavaScript - jQuery Conference SF Bay Area 2010
High Performance JavaScript - jQuery Conference SF Bay Area 2010Nicholas Zakas
 
AtlasCamp 2012 - Testing JIRA plugins smarter with TestKit
AtlasCamp 2012 - Testing JIRA plugins smarter with TestKitAtlasCamp 2012 - Testing JIRA plugins smarter with TestKit
AtlasCamp 2012 - Testing JIRA plugins smarter with TestKitWojciech Seliga
 
Node JS Express : Steps to Create Restful Web App
Node JS Express : Steps to Create Restful Web AppNode JS Express : Steps to Create Restful Web App
Node JS Express : Steps to Create Restful Web AppEdureka!
 
Utiliser Webpack dans une application Symfony
Utiliser Webpack dans une application SymfonyUtiliser Webpack dans une application Symfony
Utiliser Webpack dans une application SymfonyAlain Hippolyte
 
232 deview2013 oss를활용한분산아키텍처구현
232 deview2013 oss를활용한분산아키텍처구현232 deview2013 oss를활용한분산아키텍처구현
232 deview2013 oss를활용한분산아키텍처구현NAVER D2
 
Performance Improvements in Browsers
Performance Improvements in BrowsersPerformance Improvements in Browsers
Performance Improvements in Browsersjeresig
 

Tendances (20)

Spring Booted, But... @JCConf 16', Taiwan
Spring Booted, But... @JCConf 16', TaiwanSpring Booted, But... @JCConf 16', Taiwan
Spring Booted, But... @JCConf 16', Taiwan
 
Introduction to Apache Roller
Introduction to Apache RollerIntroduction to Apache Roller
Introduction to Apache Roller
 
Spring Boot & WebSocket
Spring Boot & WebSocketSpring Boot & WebSocket
Spring Boot & WebSocket
 
Reactive microservices with Micronaut - GR8Conf EU 2018
Reactive microservices with Micronaut - GR8Conf EU 2018Reactive microservices with Micronaut - GR8Conf EU 2018
Reactive microservices with Micronaut - GR8Conf EU 2018
 
Microservices with Spring Boot
Microservices with Spring BootMicroservices with Spring Boot
Microservices with Spring Boot
 
Apache Camel - FUSE community day London 2010 presentation
Apache Camel - FUSE community day London 2010 presentationApache Camel - FUSE community day London 2010 presentation
Apache Camel - FUSE community day London 2010 presentation
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
 
A Tour of Wyriki
A Tour of WyrikiA Tour of Wyriki
A Tour of Wyriki
 
Deploying to azure web sites
Deploying to azure web sitesDeploying to azure web sites
Deploying to azure web sites
 
HTTP, JSON, JavaScript, Map&Reduce built-in to MySQL
HTTP, JSON, JavaScript, Map&Reduce built-in to MySQLHTTP, JSON, JavaScript, Map&Reduce built-in to MySQL
HTTP, JSON, JavaScript, Map&Reduce built-in to MySQL
 
Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...
Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...
Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...
 
Architecting Large Enterprise Java Projects
Architecting Large Enterprise Java ProjectsArchitecting Large Enterprise Java Projects
Architecting Large Enterprise Java Projects
 
Red Hat and Oracle: Delivering on the Promise of Interoperability in Java EE 7
Red Hat and Oracle: Delivering on the Promise of Interoperability in Java EE 7Red Hat and Oracle: Delivering on the Promise of Interoperability in Java EE 7
Red Hat and Oracle: Delivering on the Promise of Interoperability in Java EE 7
 
Webpack Encore Symfony Live 2017 San Francisco
Webpack Encore Symfony Live 2017 San FranciscoWebpack Encore Symfony Live 2017 San Francisco
Webpack Encore Symfony Live 2017 San Francisco
 
High Performance JavaScript - jQuery Conference SF Bay Area 2010
High Performance JavaScript - jQuery Conference SF Bay Area 2010High Performance JavaScript - jQuery Conference SF Bay Area 2010
High Performance JavaScript - jQuery Conference SF Bay Area 2010
 
AtlasCamp 2012 - Testing JIRA plugins smarter with TestKit
AtlasCamp 2012 - Testing JIRA plugins smarter with TestKitAtlasCamp 2012 - Testing JIRA plugins smarter with TestKit
AtlasCamp 2012 - Testing JIRA plugins smarter with TestKit
 
Node JS Express : Steps to Create Restful Web App
Node JS Express : Steps to Create Restful Web AppNode JS Express : Steps to Create Restful Web App
Node JS Express : Steps to Create Restful Web App
 
Utiliser Webpack dans une application Symfony
Utiliser Webpack dans une application SymfonyUtiliser Webpack dans une application Symfony
Utiliser Webpack dans une application Symfony
 
232 deview2013 oss를활용한분산아키텍처구현
232 deview2013 oss를활용한분산아키텍처구현232 deview2013 oss를활용한분산아키텍처구현
232 deview2013 oss를활용한분산아키텍처구현
 
Performance Improvements in Browsers
Performance Improvements in BrowsersPerformance Improvements in Browsers
Performance Improvements in Browsers
 

En vedette

Practices and tools for building better APIs
Practices and tools for building better APIsPractices and tools for building better APIs
Practices and tools for building better APIsNLJUG
 
Introduction to Reactive with Play and Akka - Markus Jura
Introduction to Reactive with Play and Akka - Markus JuraIntroduction to Reactive with Play and Akka - Markus Jura
Introduction to Reactive with Play and Akka - Markus JuraNLJUG
 
Retro gaming with lambdas stephen chin
Retro gaming with lambdas   stephen chinRetro gaming with lambdas   stephen chin
Retro gaming with lambdas stephen chinNLJUG
 
Real-time user interfaces - sosm gewoon makkelijker - Allard Buijze
Real-time user interfaces - sosm gewoon makkelijker - Allard BuijzeReal-time user interfaces - sosm gewoon makkelijker - Allard Buijze
Real-time user interfaces - sosm gewoon makkelijker - Allard BuijzeNLJUG
 
Keynote Oracle
Keynote OracleKeynote Oracle
Keynote OracleNLJUG
 
ING : How top quality software and state-of-the-art technology leads to conti...
ING : How top quality software and state-of-the-art technology leads to conti...ING : How top quality software and state-of-the-art technology leads to conti...
ING : How top quality software and state-of-the-art technology leads to conti...NLJUG
 
JVM bytecode engineering 101
JVM bytecode engineering 101JVM bytecode engineering 101
JVM bytecode engineering 101NLJUG
 
JavaScript applicaties voor Enterprise met AngularJS
JavaScript applicaties voor Enterprise met AngularJSJavaScript applicaties voor Enterprise met AngularJS
JavaScript applicaties voor Enterprise met AngularJSNLJUG
 
Building scalable network applications with Netty
Building scalable network applications with NettyBuilding scalable network applications with Netty
Building scalable network applications with NettyNLJUG
 
Designing Distributed Programs with a Raspberry Pi cluster
Designing Distributed Programs with a Raspberry Pi clusterDesigning Distributed Programs with a Raspberry Pi cluster
Designing Distributed Programs with a Raspberry Pi clusterNLJUG
 
Integrity of data lucas jellema
Integrity of data   lucas jellemaIntegrity of data   lucas jellema
Integrity of data lucas jellemaNLJUG
 
Rethink your architecture - Marten Deinum
Rethink your architecture - Marten DeinumRethink your architecture - Marten Deinum
Rethink your architecture - Marten DeinumNLJUG
 
Effectief automatisch testen met cucumber hol bert jan schrijver and frans ...
Effectief automatisch testen met cucumber hol   bert jan schrijver and frans ...Effectief automatisch testen met cucumber hol   bert jan schrijver and frans ...
Effectief automatisch testen met cucumber hol bert jan schrijver and frans ...NLJUG
 
HoneySpider Network: a Java based system to hunt down malicious websites
HoneySpider Network: a Java based system to hunt down malicious websitesHoneySpider Network: a Java based system to hunt down malicious websites
HoneySpider Network: a Java based system to hunt down malicious websitesNLJUG
 
Event-sourced architectures with Akka - Sander Mak
Event-sourced architectures with Akka - Sander MakEvent-sourced architectures with Akka - Sander Mak
Event-sourced architectures with Akka - Sander MakNLJUG
 
Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...
Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...
Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...NLJUG
 
Performance van Java 8 en verder - Jeroen Borgers
Performance van Java 8 en verder - Jeroen BorgersPerformance van Java 8 en verder - Jeroen Borgers
Performance van Java 8 en verder - Jeroen BorgersNLJUG
 
Setting up a mini big data architecture, just for you! - Bas Geerdink
Setting up a mini big data architecture, just for you! - Bas GeerdinkSetting up a mini big data architecture, just for you! - Bas Geerdink
Setting up a mini big data architecture, just for you! - Bas GeerdinkNLJUG
 

En vedette (18)

Practices and tools for building better APIs
Practices and tools for building better APIsPractices and tools for building better APIs
Practices and tools for building better APIs
 
Introduction to Reactive with Play and Akka - Markus Jura
Introduction to Reactive with Play and Akka - Markus JuraIntroduction to Reactive with Play and Akka - Markus Jura
Introduction to Reactive with Play and Akka - Markus Jura
 
Retro gaming with lambdas stephen chin
Retro gaming with lambdas   stephen chinRetro gaming with lambdas   stephen chin
Retro gaming with lambdas stephen chin
 
Real-time user interfaces - sosm gewoon makkelijker - Allard Buijze
Real-time user interfaces - sosm gewoon makkelijker - Allard BuijzeReal-time user interfaces - sosm gewoon makkelijker - Allard Buijze
Real-time user interfaces - sosm gewoon makkelijker - Allard Buijze
 
Keynote Oracle
Keynote OracleKeynote Oracle
Keynote Oracle
 
ING : How top quality software and state-of-the-art technology leads to conti...
ING : How top quality software and state-of-the-art technology leads to conti...ING : How top quality software and state-of-the-art technology leads to conti...
ING : How top quality software and state-of-the-art technology leads to conti...
 
JVM bytecode engineering 101
JVM bytecode engineering 101JVM bytecode engineering 101
JVM bytecode engineering 101
 
JavaScript applicaties voor Enterprise met AngularJS
JavaScript applicaties voor Enterprise met AngularJSJavaScript applicaties voor Enterprise met AngularJS
JavaScript applicaties voor Enterprise met AngularJS
 
Building scalable network applications with Netty
Building scalable network applications with NettyBuilding scalable network applications with Netty
Building scalable network applications with Netty
 
Designing Distributed Programs with a Raspberry Pi cluster
Designing Distributed Programs with a Raspberry Pi clusterDesigning Distributed Programs with a Raspberry Pi cluster
Designing Distributed Programs with a Raspberry Pi cluster
 
Integrity of data lucas jellema
Integrity of data   lucas jellemaIntegrity of data   lucas jellema
Integrity of data lucas jellema
 
Rethink your architecture - Marten Deinum
Rethink your architecture - Marten DeinumRethink your architecture - Marten Deinum
Rethink your architecture - Marten Deinum
 
Effectief automatisch testen met cucumber hol bert jan schrijver and frans ...
Effectief automatisch testen met cucumber hol   bert jan schrijver and frans ...Effectief automatisch testen met cucumber hol   bert jan schrijver and frans ...
Effectief automatisch testen met cucumber hol bert jan schrijver and frans ...
 
HoneySpider Network: a Java based system to hunt down malicious websites
HoneySpider Network: a Java based system to hunt down malicious websitesHoneySpider Network: a Java based system to hunt down malicious websites
HoneySpider Network: a Java based system to hunt down malicious websites
 
Event-sourced architectures with Akka - Sander Mak
Event-sourced architectures with Akka - Sander MakEvent-sourced architectures with Akka - Sander Mak
Event-sourced architectures with Akka - Sander Mak
 
Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...
Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...
Modularity and Domain Driven Design; a killer Combination? - Tom de Wolf & St...
 
Performance van Java 8 en verder - Jeroen Borgers
Performance van Java 8 en verder - Jeroen BorgersPerformance van Java 8 en verder - Jeroen Borgers
Performance van Java 8 en verder - Jeroen Borgers
 
Setting up a mini big data architecture, just for you! - Bas Geerdink
Setting up a mini big data architecture, just for you! - Bas GeerdinkSetting up a mini big data architecture, just for you! - Bas Geerdink
Setting up a mini big data architecture, just for you! - Bas Geerdink
 

Similaire à Apache Wicket: 10 jaar en verder - Martijn Dashorst

Wicket 10 years and beyond
Wicket   10 years and beyond Wicket   10 years and beyond
Wicket 10 years and beyond Martijn Dashorst
 
자바 웹 개발 시작하기 (1주차 : 웹 어플리케이션 체험 실습)
자바 웹 개발 시작하기 (1주차 : 웹 어플리케이션 체험 실습)자바 웹 개발 시작하기 (1주차 : 웹 어플리케이션 체험 실습)
자바 웹 개발 시작하기 (1주차 : 웹 어플리케이션 체험 실습)DK Lee
 
Developing Java Web Applications
Developing Java Web ApplicationsDeveloping Java Web Applications
Developing Java Web Applicationshchen1
 
GWT Web Socket and data serialization
GWT Web Socket and data serializationGWT Web Socket and data serialization
GWT Web Socket and data serializationGWTcon
 
Introduction to the Servlet / JSP course
Introduction to the Servlet / JSP course Introduction to the Servlet / JSP course
Introduction to the Servlet / JSP course JavaEE Trainers
 
Knowledge Sharing : Java Servlet
Knowledge Sharing : Java ServletKnowledge Sharing : Java Servlet
Knowledge Sharing : Java ServletFahmi Jafar
 
JSR 168 Portal - Overview
JSR 168 Portal - OverviewJSR 168 Portal - Overview
JSR 168 Portal - OverviewVinay Kumar
 
Web container and Apache Tomcat
Web container and Apache TomcatWeb container and Apache Tomcat
Web container and Apache TomcatAuwal Amshi
 
Writing highly scalable WebSocket using the Atmosphere Framework and Scala
Writing highly scalable WebSocket using the Atmosphere Framework and ScalaWriting highly scalable WebSocket using the Atmosphere Framework and Scala
Writing highly scalable WebSocket using the Atmosphere Framework and Scalajfarcand
 
Ajax Frameworks in the J(2)EE Environment
Ajax Frameworks in the J(2)EE EnvironmentAjax Frameworks in the J(2)EE Environment
Ajax Frameworks in the J(2)EE Environmentstarchaser
 
Servlet and jsp development with eclipse wtp
Servlet and jsp development with eclipse wtpServlet and jsp development with eclipse wtp
Servlet and jsp development with eclipse wtpodilodif
 
Java Servlets
Java ServletsJava Servlets
Java ServletsNitin Pai
 
Full Stack Reactive with React and Spring WebFlux - Dublin JUG 2019
Full Stack Reactive with React and Spring WebFlux - Dublin JUG 2019Full Stack Reactive with React and Spring WebFlux - Dublin JUG 2019
Full Stack Reactive with React and Spring WebFlux - Dublin JUG 2019Matt Raible
 
Web Applications and Deployment
Web Applications and DeploymentWeb Applications and Deployment
Web Applications and DeploymentBG Java EE Course
 
Html5 and beyond the next generation of mobile web applications - Touch Tou...
Html5 and beyond   the next generation of mobile web applications - Touch Tou...Html5 and beyond   the next generation of mobile web applications - Touch Tou...
Html5 and beyond the next generation of mobile web applications - Touch Tou...RIA RUI Society
 
Websockets on the JVM: Atmosphere to the rescue!
Websockets on the JVM: Atmosphere to the rescue!Websockets on the JVM: Atmosphere to the rescue!
Websockets on the JVM: Atmosphere to the rescue!jfarcand
 

Similaire à Apache Wicket: 10 jaar en verder - Martijn Dashorst (20)

Wicket 10 years and beyond
Wicket   10 years and beyond Wicket   10 years and beyond
Wicket 10 years and beyond
 
자바 웹 개발 시작하기 (1주차 : 웹 어플리케이션 체험 실습)
자바 웹 개발 시작하기 (1주차 : 웹 어플리케이션 체험 실습)자바 웹 개발 시작하기 (1주차 : 웹 어플리케이션 체험 실습)
자바 웹 개발 시작하기 (1주차 : 웹 어플리케이션 체험 실습)
 
Developing Java Web Applications
Developing Java Web ApplicationsDeveloping Java Web Applications
Developing Java Web Applications
 
GWT Web Socket and data serialization
GWT Web Socket and data serializationGWT Web Socket and data serialization
GWT Web Socket and data serialization
 
Introduction to the Servlet / JSP course
Introduction to the Servlet / JSP course Introduction to the Servlet / JSP course
Introduction to the Servlet / JSP course
 
Knowledge Sharing : Java Servlet
Knowledge Sharing : Java ServletKnowledge Sharing : Java Servlet
Knowledge Sharing : Java Servlet
 
Tomcat + other things
Tomcat + other thingsTomcat + other things
Tomcat + other things
 
JSR 168 Portal - Overview
JSR 168 Portal - OverviewJSR 168 Portal - Overview
JSR 168 Portal - Overview
 
Web container and Apache Tomcat
Web container and Apache TomcatWeb container and Apache Tomcat
Web container and Apache Tomcat
 
AJppt.pptx
AJppt.pptxAJppt.pptx
AJppt.pptx
 
Beginning In J2EE
Beginning In J2EEBeginning In J2EE
Beginning In J2EE
 
Writing highly scalable WebSocket using the Atmosphere Framework and Scala
Writing highly scalable WebSocket using the Atmosphere Framework and ScalaWriting highly scalable WebSocket using the Atmosphere Framework and Scala
Writing highly scalable WebSocket using the Atmosphere Framework and Scala
 
Ajax Frameworks in the J(2)EE Environment
Ajax Frameworks in the J(2)EE EnvironmentAjax Frameworks in the J(2)EE Environment
Ajax Frameworks in the J(2)EE Environment
 
Servlet and jsp development with eclipse wtp
Servlet and jsp development with eclipse wtpServlet and jsp development with eclipse wtp
Servlet and jsp development with eclipse wtp
 
Java Servlets
Java ServletsJava Servlets
Java Servlets
 
Full Stack Reactive with React and Spring WebFlux - Dublin JUG 2019
Full Stack Reactive with React and Spring WebFlux - Dublin JUG 2019Full Stack Reactive with React and Spring WebFlux - Dublin JUG 2019
Full Stack Reactive with React and Spring WebFlux - Dublin JUG 2019
 
Web Applications and Deployment
Web Applications and DeploymentWeb Applications and Deployment
Web Applications and Deployment
 
Html5 and beyond the next generation of mobile web applications - Touch Tou...
Html5 and beyond   the next generation of mobile web applications - Touch Tou...Html5 and beyond   the next generation of mobile web applications - Touch Tou...
Html5 and beyond the next generation of mobile web applications - Touch Tou...
 
Jsp Comparison
 Jsp Comparison Jsp Comparison
Jsp Comparison
 
Websockets on the JVM: Atmosphere to the rescue!
Websockets on the JVM: Atmosphere to the rescue!Websockets on the JVM: Atmosphere to the rescue!
Websockets on the JVM: Atmosphere to the rescue!
 

Plus de NLJUG

The future of Web-Scale - Johan Tillema, Rene Boere & Chris Quach
The future of Web-Scale - Johan Tillema, Rene Boere & Chris QuachThe future of Web-Scale - Johan Tillema, Rene Boere & Chris Quach
The future of Web-Scale - Johan Tillema, Rene Boere & Chris QuachNLJUG
 
Speedy perception trumps speedy reception–smart asynchronous interactions - L...
Speedy perception trumps speedy reception–smart asynchronous interactions - L...Speedy perception trumps speedy reception–smart asynchronous interactions - L...
Speedy perception trumps speedy reception–smart asynchronous interactions - L...NLJUG
 
Decoding the airspace above you with Java and $7 hardware - Bert Jan Schrijver
Decoding the airspace above you with Java and $7 hardware - Bert Jan SchrijverDecoding the airspace above you with Java and $7 hardware - Bert Jan Schrijver
Decoding the airspace above you with Java and $7 hardware - Bert Jan SchrijverNLJUG
 
Using Docker to Develop, Test and Run Maven Projects - Wouter Danes
Using Docker to Develop, Test and Run Maven Projects - Wouter DanesUsing Docker to Develop, Test and Run Maven Projects - Wouter Danes
Using Docker to Develop, Test and Run Maven Projects - Wouter DanesNLJUG
 
Kill the mutants and test your tests - Roy van Rijn
Kill the mutants and test your tests - Roy van RijnKill the mutants and test your tests - Roy van Rijn
Kill the mutants and test your tests - Roy van RijnNLJUG
 
The end of traditional enterprise IT - ING's journey to the next generation I...
The end of traditional enterprise IT - ING's journey to the next generation I...The end of traditional enterprise IT - ING's journey to the next generation I...
The end of traditional enterprise IT - ING's journey to the next generation I...NLJUG
 
Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...
Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...
Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...NLJUG
 
Workshop angular dart presentatie - Atos
Workshop angular dart presentatie - AtosWorkshop angular dart presentatie - Atos
Workshop angular dart presentatie - AtosNLJUG
 
Workshop spring boot presentatie - Atos
Workshop spring boot presentatie - AtosWorkshop spring boot presentatie - Atos
Workshop spring boot presentatie - AtosNLJUG
 
Cultivating the jenkins job jungle with groovy - Patrick van Dissel
Cultivating the jenkins job jungle with groovy - Patrick van DisselCultivating the jenkins job jungle with groovy - Patrick van Dissel
Cultivating the jenkins job jungle with groovy - Patrick van DisselNLJUG
 
Evolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopper
Evolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopperEvolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopper
Evolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopperNLJUG
 
Opening - Bert Ertman
Opening - Bert ErtmanOpening - Bert Ertman
Opening - Bert ErtmanNLJUG
 
Returning the right results - Jettro Coenradie
Returning the right results - Jettro CoenradieReturning the right results - Jettro Coenradie
Returning the right results - Jettro CoenradieNLJUG
 
Reactive programming met Java 8 en Java EE 7 - Martijn Blankestijn
Reactive programming met Java 8 en Java EE 7 - Martijn BlankestijnReactive programming met Java 8 en Java EE 7 - Martijn Blankestijn
Reactive programming met Java 8 en Java EE 7 - Martijn BlankestijnNLJUG
 
Gebruik dezelfde Docker container voor Java applicaties tijdens ontwikkelen e...
Gebruik dezelfde Docker container voor Java applicaties tijdens ontwikkelen e...Gebruik dezelfde Docker container voor Java applicaties tijdens ontwikkelen e...
Gebruik dezelfde Docker container voor Java applicaties tijdens ontwikkelen e...NLJUG
 
A Storm of Drones - Dennis Vredeveld
A Storm of Drones - Dennis Vredeveld A Storm of Drones - Dennis Vredeveld
A Storm of Drones - Dennis Vredeveld NLJUG
 
Shootout! template engines on the jvm
Shootout! template engines on the jvmShootout! template engines on the jvm
Shootout! template engines on the jvmNLJUG
 
On the integrity of data in Java Applications
On the integrity of data in Java ApplicationsOn the integrity of data in Java Applications
On the integrity of data in Java ApplicationsNLJUG
 
Data Science with R for Java Developers
Data Science with R for Java DevelopersData Science with R for Java Developers
Data Science with R for Java DevelopersNLJUG
 
Modular JavaScript
Modular JavaScriptModular JavaScript
Modular JavaScriptNLJUG
 

Plus de NLJUG (20)

The future of Web-Scale - Johan Tillema, Rene Boere & Chris Quach
The future of Web-Scale - Johan Tillema, Rene Boere & Chris QuachThe future of Web-Scale - Johan Tillema, Rene Boere & Chris Quach
The future of Web-Scale - Johan Tillema, Rene Boere & Chris Quach
 
Speedy perception trumps speedy reception–smart asynchronous interactions - L...
Speedy perception trumps speedy reception–smart asynchronous interactions - L...Speedy perception trumps speedy reception–smart asynchronous interactions - L...
Speedy perception trumps speedy reception–smart asynchronous interactions - L...
 
Decoding the airspace above you with Java and $7 hardware - Bert Jan Schrijver
Decoding the airspace above you with Java and $7 hardware - Bert Jan SchrijverDecoding the airspace above you with Java and $7 hardware - Bert Jan Schrijver
Decoding the airspace above you with Java and $7 hardware - Bert Jan Schrijver
 
Using Docker to Develop, Test and Run Maven Projects - Wouter Danes
Using Docker to Develop, Test and Run Maven Projects - Wouter DanesUsing Docker to Develop, Test and Run Maven Projects - Wouter Danes
Using Docker to Develop, Test and Run Maven Projects - Wouter Danes
 
Kill the mutants and test your tests - Roy van Rijn
Kill the mutants and test your tests - Roy van RijnKill the mutants and test your tests - Roy van Rijn
Kill the mutants and test your tests - Roy van Rijn
 
The end of traditional enterprise IT - ING's journey to the next generation I...
The end of traditional enterprise IT - ING's journey to the next generation I...The end of traditional enterprise IT - ING's journey to the next generation I...
The end of traditional enterprise IT - ING's journey to the next generation I...
 
Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...
Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...
Web-scale op basis van Hadoop en Akka Reactive Streams - Johan Tillema, Rene ...
 
Workshop angular dart presentatie - Atos
Workshop angular dart presentatie - AtosWorkshop angular dart presentatie - Atos
Workshop angular dart presentatie - Atos
 
Workshop spring boot presentatie - Atos
Workshop spring boot presentatie - AtosWorkshop spring boot presentatie - Atos
Workshop spring boot presentatie - Atos
 
Cultivating the jenkins job jungle with groovy - Patrick van Dissel
Cultivating the jenkins job jungle with groovy - Patrick van DisselCultivating the jenkins job jungle with groovy - Patrick van Dissel
Cultivating the jenkins job jungle with groovy - Patrick van Dissel
 
Evolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopper
Evolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopperEvolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopper
Evolutionary Algorithms: the key to solving complex Java puzzles! - Bas knopper
 
Opening - Bert Ertman
Opening - Bert ErtmanOpening - Bert Ertman
Opening - Bert Ertman
 
Returning the right results - Jettro Coenradie
Returning the right results - Jettro CoenradieReturning the right results - Jettro Coenradie
Returning the right results - Jettro Coenradie
 
Reactive programming met Java 8 en Java EE 7 - Martijn Blankestijn
Reactive programming met Java 8 en Java EE 7 - Martijn BlankestijnReactive programming met Java 8 en Java EE 7 - Martijn Blankestijn
Reactive programming met Java 8 en Java EE 7 - Martijn Blankestijn
 
Gebruik dezelfde Docker container voor Java applicaties tijdens ontwikkelen e...
Gebruik dezelfde Docker container voor Java applicaties tijdens ontwikkelen e...Gebruik dezelfde Docker container voor Java applicaties tijdens ontwikkelen e...
Gebruik dezelfde Docker container voor Java applicaties tijdens ontwikkelen e...
 
A Storm of Drones - Dennis Vredeveld
A Storm of Drones - Dennis Vredeveld A Storm of Drones - Dennis Vredeveld
A Storm of Drones - Dennis Vredeveld
 
Shootout! template engines on the jvm
Shootout! template engines on the jvmShootout! template engines on the jvm
Shootout! template engines on the jvm
 
On the integrity of data in Java Applications
On the integrity of data in Java ApplicationsOn the integrity of data in Java Applications
On the integrity of data in Java Applications
 
Data Science with R for Java Developers
Data Science with R for Java DevelopersData Science with R for Java Developers
Data Science with R for Java Developers
 
Modular JavaScript
Modular JavaScriptModular JavaScript
Modular JavaScript
 

Dernier

Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Angeliki Cooney
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...apidays
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKJago de Vreede
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Jeffrey Haguewood
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 

Dernier (20)

Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 

Apache Wicket: 10 jaar en verder - Martijn Dashorst

  • 1. APACHE WICKET Apache Wicket 10 years and beyond Martijn Dashorst topicus onderwijs @dashorst
  • 2. a brief history of Wicket the current state of Wicket the future of Wicket
  • 3.
  • 6. started in 2004 at topicus without any knowledge of web programming
  • 9. using maverick velocity hibernate jasperreports
  • 10. lots of XML configuration
  • 11. 1 change requires N files to be modified (for large values of N) <command name="admin.tabelbeheer.edittoetsonderdeel"> <controller class="nl.topicus.bao.web.ctrl.lab.toetsen. <view name="success" path="/admin/tabelbeheer/toetsen/e <transform path="/mlayout/mainlayout.vm"> <param name="_pagetitle" value="Beheer Tabellen </transform> </view> <view name="error" path="/admin/tabelbeheer/toetsen/edi <transform path="/mlayout/mainlayout.vm"> <param name="_pagetitle" value="Beheer Tabellen </transform> </view> <view name="list" path="admin.tabelbeheer.edittoets.m" </command>
  • 13. no back button support no multi-tab support
  • 15. little to no reuse </tr> #if($model.bean.absentieRegels.empty) <tr> <td colspan="19" class="border-r">#formname('groep.absent' </tr> #else #set($columnIndexes=[1,2,3,4,5,6,7,8,9,10]) #foreach($row in $model.bean.absentieRegels) <tr> <td class="columnvalue">$arrayTool.elementAt($row, 0)</td #foreach($index in $columnIndexes) #set($melding=$arrayTool.elementAt($row, $index))
  • 16. complex UI neigh impossible
  • 17. a framework that makes reuse possible, minimises configuration, server side state management easy and is as type safe as possible
  • 18. Action Framework Anvil Apache Click Apache MyFaces Apache Shale Apache Sling Apache Struts Apache Struts 2 Apache Tapestry Apache Turbine Apache Wicket AppFuse Aranea Web Framework AribaWeb Aurora Baritus Barracuda Bento Bishop Brill Calyxo Cameleon Canyamo Caramba Cassandra Chiba Chrysalis Dinamica Dovetail DWR Echo Eclipse RAP Expresso fleXive Flower framework Folium FormEngine Genie Grails GWT Hamlets Helma Induction ItsNat Jacquard Jaffa Japple JAT JATO JBanana JBoss Seam Jeenius JFormular JOSSO JPublish JSPWidget Jspx-bay jStatemachine Jucas JVx JWAA JWarp jWic jZeno jZonic Macaw Makumba Maverick Melati Mentawai Millstone Nacho Niggle OpenEmcee OpenLaszlo OpenXava Oracle ADF OXF Pandora Playframework Pustefix Restlet RIFE Roma Meta Framework RSF Scope SerfJ Shocks Smile SOFIA Sombrero Spark Spring MVC Strecks Stripes Swinglets SwingWeb Tapestry TeaServlet ThinWire Trimpath Junction Turbine Vaadin Verge VRaptor Vroom Warfare Wavemaker WebObjects WebOnSwing WebWork wingS Xoplon Ze Framework ZK ztemplates
  • 19. 120+ java web frameworks
  • 21. public class EditPage extends WebPage { private Person person; public EditPage(Person person) { this.person = person; add(new Button("save") { @Override public void onSubmit() { Entities.save(person); setResponsePage(new ShowPage(person)); } }); } }
  • 22. a framework that makes reuse possible, minimises configuration, server side state management easy and is as type safe as possible ✓ ✓ ✓ ✓
  • 23. Action Framework Anvil Apache Click Apache MyFaces Apache Shale Apache Sling Apache Struts Apache Struts 2 Apache Tapestry Apache Turbine Apache Wicket AppFuse Aranea Web Framework AribaWeb Aurora Baritus Barracuda Bento Bishop Brill Calyxo Cameleon Canyamo Caramba Cassandra Chiba Chrysalis Dinamica Dovetail DWR Echo Eclipse RAP Expresso fleXive Flower framework Folium FormEngine Genie Grails GWT Hamlets Helma Induction ItsNat Jacquard Jaffa Japple JAT JATO JBanana JBoss Seam Jeenius JFormular JOSSO JPublish JSPWidget Jspx-bay jStatemachine Jucas JVx JWAA JWarp jWic jZeno jZonic Macaw Makumba Maverick Melati Mentawai Millstone Nacho Niggle OpenEmcee OpenLaszlo OpenXava Oracle ADF OXF Pandora Playframework Pustefix Restlet RIFE Roma Meta Framework RSF Scope SerfJ Shocks Smile SOFIA Sombrero Spark Spring MVC Strecks Stripes Swinglets SwingWeb Tapestry TeaServlet ThinWire Trimpath Junction Turbine Vaadin Verge VRaptor Vroom Warfare Wavemaker WebObjects WebOnSwing WebWork wingS Xoplon Ze Framework ZK ztemplates
  • 24. Action Framework Anvil Apache Click Apache MyFaces Apache Shale Apache Sling Apache Struts Apache Struts 2 Apache Tapestry Apache Turbine Apache Wicket AppFuse Aranea Web Framework AribaWeb Aurora Baritus Barracuda Bento Bishop Brill Calyxo Cameleon Canyamo Caramba Cassandra Chiba Chrysalis Dinamica Dovetail DWR Echo Eclipse RAP Expresso fleXive Flower framework Folium FormEngine Genie Grails GWT Hamlets Helma Induction ItsNat Jacquard Jaffa Japple JAT JATO JBanana JBoss Seam Jeenius JFormular JOSSO JPublish JSPWidget Jspx-bay jStatemachine Jucas JVx JWAA JWarp jWic jZeno jZonic Macaw Makumba Maverick Melati Mentawai Millstone Nacho Niggle OpenEmcee OpenLaszlo OpenXava Oracle ADF OXF Pandora Playframework Pustefix Restlet RIFE Roma Meta Framework RSF Scope SerfJ Shocks Smile SOFIA Sombrero Spark Spring MVC Strecks Stripes Swinglets SwingWeb Tapestry TeaServlet ThinWire Trimpath Junction Turbine Vaadin Verge VRaptor Vroom Warfare Wavemaker WebObjects WebOnSwing WebWork wingS Xoplon Ze Framework ZK ztemplates
  • 25. 15 java web frameworks alive i.e. made any release in the last year
  • 27. What is Wicket? Apache Wicket From Wikipedia, the free encyclopedia Apache Wicket, commonly referred to as Wicket, is a lightweight component-based web application framework for the Java programming language conceptually similar to JavaServer Faces and Tapestry. It was originally written by Jonathan Locke in April 2004. Version 1.0 was released in June 2005. It graduated into an Apache top-level project in June 2007.[2]
  • 28. A brief history of Wicket
  • 29. 2004
  • 31. 2004 2005 codehaus.org The Server Side
  • 32. 2004 2005 codehaus.org The Server Side
  • 33. 2004 codehaus.org 1.0 1.1 The Server Side JavaOne 2006 1.2 2005 AJAX
  • 34. 2007
  • 36. 2007 2008 2009 1.3 1.4 2010 2011 1.5
  • 37. 2007 2008 2009 1.3 1.4 2010 2011 1.5
  • 38. 2012 6.0 2013 2014 6.10 6.14 6.12 6.2 6.4 6.6 6.8 6.1 6.5 6.9 6.13 6.11 7.0.0-M4 6.18 7.0.0-M2 6.16 6.15 7.0.0-M1 6.3 6.7 6.17 7.0.0-M3
  • 39. That's of Apache Wicket! 10 years
  • 40. The state of Wicket
  • 41. 1. core 2. extensions 3. spring 4. datetime 5. auth-roles
  • 44. User Manual 195 25 Wicket Internals 25.1 Page storing During request handling, Wicket manages page instances through interface org.apache.wicket.request.handler.IPageProvider. This interface creates a new page instance or loads a previously serialized page instance if we provide the corrisponding page id. IPageProvider delegates page creation and retrieval to interface org.apache.wicket.request.mapper.IPageSource. When page class is provided IPageSource delegates page creation to interface org.apache.wicket.IPageFactory, while when page id is provided it uses interface org.apache.wicket.page.IPageManager to load the previously serialized page. The following workflow diagram summarizes the mechanism seen so far: IPageManager org.apache.wicket.page.IPageManager's task is to manage which pages have been used in a request and store their last state in the backing stores, namely IPageStore. The default implementation org.apache.wicket.page.PageStoreManager collects all stateful pages which have been used in the request cycle (more than one page can be used in a single request if for example setResponsePage() or RestartResponseException is used). At the end of the request all collected page instances are being stored in the first level cache - http session. They are stored in http session attribute named "wicket:persistentPageManagerData-APPLICATION_NAME" and passed to the underlying IPageStore . When the next http request comes IPageProvider will ask for page with specific id and PageStoreManager will look first in the http session and if no match is found then it will delegate to the IPageStore. At the end of the second request the http session based cache is being overwritten completely with the newly used page instances. To setup another IPageManager implementat ion use org.apache.wicket.Application.setPageManagerProvider(IPageManagerProvider). The custom IPageManager implementation may or may not use IPageStore/IDataStore. IPageStore org.apache.wicket.pageStore.IPageStore's role is to mediate the storing and loading of pages done by the under lying IDataStore. The defaul t implementat ion org.apache.wicket.pageStore.DefaultPageStore pre-processes the pages before passing them to As you can see above, the Exception gets raised during the initialization of the WicketTester instance even before the actual test method gets executed. Even though we have applied rather cool and simple annotation based test configuration already described and passed in perfectly well prepared ApplicationContext instance to the WicketTester instance in the constructor, somewhere down the rabbit hole someone complained that no WebApplicationContext instance could have been found which seems to be required in order to initialize the WicketTester properly. The problem that we run against here is due to the fact that SpringComponentInjector during its own initialization is trying to get hold of an according Spring's ApplicationContext instance that would normally be there in a runtime environment but does not find any since we are running in a test environment currently. SpringComponentInjector delegates to Spring's own WebApplicationContextUtils class to retrieve the instance of ApplicationContext out of the ServletContext which is perfectly fine for a runtime environment but is unfortunately failing in a test environment: 183 public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc) throws IllegalStateException { WebApplicationContext wac = getWebApplicationContext(sc); if (wac == null) { throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?"); } return wac; } If you still remember we defined a ContextLoaderListener in our web.xml file as part of the configuration of our runtime environment that makes sure an according WebApplicationContext instance gets initialized and registered against the ServletContext properly. Luckily, this problem can easily be solved if we slightly change the way we initialize SpringComponentInjector in our main MyWebApplication class. Apart from the constructor that we have used so far, there is another constructor in the SpringComponentInjector class that expects the caller to provide it with an according ApplicationContext instance rather than trying to resolve one on its own: public SpringComponentInjector(WebApplication webapp, ApplicationContext ctx, boolean wrapInProxies) { if (webapp == null) { throw new IllegalArgumentException("Argument [[webapp]] cannot be null"); } if (ctx == null) { throw new IllegalArgumentException("Argument [[ctx]] cannot be null"); } // store context in application's metadata … webapp.setMetaData(CONTEXT_KEY, new ApplicationContextHolder(ctx)); // … and create and register the annotation aware injector InjectorHolder.setInjector(new AnnotSpringInjector(new ContextLocator(),
  • 45. In a Nutshell, Wicket... …has had 18,255 commits made by 62 contributors representing 318,037 lines of code …is mostly written in Java with a well-commented source code …has a well established, mature codebase maintained by a large development team with stable Y-O-Y commits …took an estimated 84 years of effort (COCOMO model) starting with its first commit in September, 2004 ending with its most recent commit 1 days ago – openhub.net report for Wicket
  • 46.
  • 47.
  • 48.
  • 49.
  • 50. The future of Wicket
  • 51. Wicket 1.4 security releases only
  • 52. Wicket 1.5 security releases only
  • 56. semi-monthly releases mainly bug fixes some new minor features
  • 62. public class HomePage extends WebPage { public HomePage() { add(new Label("title", "Hello!")); } }
  • 63. public class HomePage extends WebPage { public HomePage() { add(new Label("title", "Hello!")); } } <html> <body> <h1 wicket:id="title"></h1> </body> </html>
  • 64. public class HomePage extends WebPage { public HomePage() { add(new Label("title", "Hello!")); } } <html> <body> <h1 wicket:id="title"></h1> </body> </html>
  • 65. Add a <div> around content...
  • 66. <html> <body> <div wicket:id="container"> <h1 wicket:id="title"></h1> </div> </body> </html>
  • 67. <html> <body> <div wicket:id="container"> <h1 wicket:id="title"></h1> </div> </body> </html> public class HomePage extends WebPage { public HomePage() { add(new WebMarkupContainer("container")); add(new Label("title", "Hello!")); } }
  • 68. <html> <body> <div wicket:id="container"> <h1 wicket:id="title"></h1> </div> </body> </html> public class HomePage extends WebPage { public HomePage() { add(new WebMarkupContainer("container")); add(new Label("title", "Hello!")); } }
  • 69. in Wicket code always follows markup
  • 70. <html> <body> <div wicket:id="container"> <h1 wicket:id="title"></h1> </div> </body> </html>
  • 71. <html> <body> <div wicket:id="container"> <h1 wicket:id="title"></h1> </div> </body> </html> public class HomePage extends WebPage { public HomePage() { WebMarkupContainer container = new WebMarkupContainer("container"); add(container); add(new Label("title", "Hello!")); } }
  • 72. <html> <body> <div wicket:id="container"> <h1 wicket:id="title"></h1> </div> </body> </html> public class HomePage extends WebPage { public HomePage() { WebMarkupContainer container = new WebMarkupContainer("container"); add(container); add(new Label("title", "Hello!")); } }
  • 73. <html> <body> <div wicket:id="container"> <h1 wicket:id="title"></h1> </div> </body> </html> public class HomePage extends WebPage { public HomePage() { WebMarkupContainer container = new WebMarkupContainer("container"); add(container); container.add(new Label("title", "Hello!")); } }
  • 74. in Wicket or does it? code always follows markup
  • 75. Enter Component Queuing (coming to you in wicket 7)
  • 76. What if we delay adding components? Queue components until their location in the markup hierarchy is know markupContainer.add(new Label(...)); markupContainer.queue(new Label(...));
  • 77. public class HomePage extends WebPage { public HomePage() { WebMarkupContainer container = new WebMarkupContainer("container"); add(container); container.add(new Label("title", "Hello!")); } } public class HomePage extends WebPage { public HomePage() { queue(new WebMarkupContainer("container")); queue(new Label("title", "Hello!")); } }
  • 78. <html> <body> <div wicket:id="container"> <html> <body> <header><h1 wicket:id="title"></h1></header> <div wicket:id="container"> ... </div> </body> </html> <h1 wicket:id="title"></h1> </div> </body> </html>
  • 80. queue(new Label("label", "Some text")); queue(new Label("label", "Other text"));
  • 81. queue(new Label("label", "Some text")); queue(new Label("label", "Other text"));
  • 82. Restrictions of Queuing: Ancestors queue(new Label("first")); queue(new Label("last")); WebMarkupContainer secure=new WebMarkupContainer("secure") { public void onConfigure() { super.onConfigure(); setVisible(isViewingOwnProfile()); } }; queue(secure); secure.queue(new Label("creditCardNumber")); secure.queue(new Label("creditCardExpiry"));
  • 83. <h3> Welcome, <span wicket:id="first"></span> <span wicket:id="last"></span>! </h3> <fieldset wicket:id="secure"> <legend>Secure</legend> <dt>Card expiry: <i wicket:id="creditCardExpiry"> <dt>Card number: <i wicket:id="creditCardNumber"> </fieldset>
  • 84. <h3> Welcome, <span wicket:id="first"></span> <span wicket:id="last"></span>! </h3> <fieldset wicket:id="secure"> <legend>Secure</legend> <dt>Card expiry: <i wicket:id="creditCardExpiry"> <dt>Card number: <i wicket:id="creditCardNumber"> </fieldset>
  • 85. <h3> Welcome, <span wicket:id="first"></span> <span wicket:id="last"></span>! </h3> <fieldset wicket:id="secure"> <legend>Secure</legend> <dt>Card expiry: <i wicket:id="creditCardExpiry"> </fieldset> <dt>Card number: <i wicket:id="creditCardNumber">
  • 86. <h3> Welcome, <span wicket:id="first"></span> <span wicket:id="last"></span>! </h3> <fieldset wicket:id="secure"> <legend>Secure</legend> <dt>Card expiry: <i wicket:id="creditCardExpiry"> </fieldset> <dt>Card number: <i wicket:id="creditCardNumber">
  • 87. <fieldset wicket:id="secure"> <h3> Welcome, <span wicket:id="first"></span> <span wicket:id="last"></span>! </h3> <legend>Secure</legend> <dt>Card expiry: <i wicket:id="creditCardExpiry"> <dt>Card number: <i wicket:id="creditCardNumber"> </fieldset>
  • 88. <fieldset wicket:id="secure"> <h3> Welcome, <span wicket:id="first"></span> <span wicket:id="last"></span>! </h3> <legend>Secure</legend> <dt>Card expiry: <i wicket:id="creditCardExpiry"> <dt>Card number: <i wicket:id="creditCardNumber"> </fieldset>
  • 89. Component Queuing • Wicket 7 feature • Prefer queue() when markup hierarchy can be altered • Uniqueness of Wicket IDs still requirement at same level of queuing • Can move down into child markup hierarchy • Can't move up the markup hierarchy
  • 92. PROJECT LAMBDA “functional” programming in Java
  • 93. public interface ILinkListener { void onLickClicked(); } ILinkListener l = new ILinkListener(){ @Override public void onLinkClicked() { System.out.println("Klik"); } }
  • 94. public interface ILinkListener { void onLickClicked(); } ILinkListener l = () -> { System.out.println("Klik"); }
  • 95. ILinkListener l = new ILinkListener(){ ILinkListener l = () -> { System.out.println("Klik"); } @Override public void onLinkClicked() { System.out.println("Klik"); } } or
  • 96. add(new Link<Void>("save") { @Override public void onClick() { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage()) } });
  • 97. add(new Link<Void>("save") { @Override public void onClick() { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage()) } });
  • 98. add(new Link<>("save").onClick(()-> { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage()) }); no more type information
  • 99. private void onSave() { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage()) }
  • 100. private void onSave() { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage()) } add(new Link<Void>("save") .onClick(this::onSave));
  • 101. A link with onclick, visibility and body
  • 104. add(new Link<Void>("like") { @Override public void onClick() { person.likedBy(me); } });
  • 105. add(new Link<Void>("like") { @Override public void onClick() { person.likedBy(me); } @Override public boolean isVisible() { return person.isNotLiked(); } });
  • 106. add(new Link<Void>("like") { @Override public void onClick() { person.likedBy(me); } @Override public boolean isVisible() { return person.isNotLiked(); } }.setBody());
  • 107. add(new Link<Void>("like") { @Override public void onClick() { person.likedBy(me); } @Override public boolean isVisible() { return person.isNotLiked(); } }.setBody(new AbstractReadOnlyModel<String>() { }));
  • 108. add(new Link<Void>("like") { @Override public void onClick() { person.likedBy(me); } @Override public boolean isVisible() { return person.isNotLiked(); } }.setBody(new AbstractReadOnlyModel<String>() { @Override public String getObject() { } }));
  • 109. add(new Link<Void>("like") { @Override public void onClick() { person.likedBy(me); } @Override public boolean isVisible() { return person.isNotLiked(); } }.setBody(new AbstractReadOnlyModel<String>() { @Override public String getObject() { StringBuilder sb = new StringBuilder("Like "); sb.append(person.getFirstName()); return sb.toString(); } }));
  • 110. A link with onclick, visibility and body
  • 113. add(new Link<>("like") .visible(() -> person.isNotLiked()) );
  • 114. add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) );
  • 115. add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) .body(() -> { }) );
  • 116. add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) .body(() -> { StringBuilder sb = new StringBuilder("Like "); sb.append(person.getFirstName()); return sb.toString(); }) );
  • 117. add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) .body(() -> { StringBuilder sb = new StringBuilder("Like "); sb.append(person.getFirstName()); return sb.toString(); }) ); add(new Link<Void>("like") { @Override public void onClick() { person.likedBy(me); } @Override public boolean isVisible() { return person.isNotLiked(); } }.setBody(new AbstractReadOnlyModel<String>() { @Override public String getObject() { StringBuilder sb = new StringBuilder("Like "); sb.append(person.getFirstName()); return sb.toString(); } })); Anon inner classes: 17 lines Java 8 lambdas: 9 lines
  • 120. ScriptEngineManager m = new ScriptEngineManager(); ScriptEngine nashorn = m.getEngineByName("nashorn"); nashorn.put("age", validatable.getValue()); String js = "age >= 18"; try { Object result = nashorn.eval(js); if(!((Boolean)result) { ValidationError e = new ValidationError(); validatable.error(e); } } catch(Exception e) { }
  • 121. ScriptEngineManager m = new ScriptEngineManager(); ScriptEngine nashorn = m.getEngineByName("nashorn"); nashorn.put("age", validatable.getValue()); String js = "age >= 18"; try { Object result = nashorn.eval(js); if(!((Boolean)result) { ValidationError e = new ValidationError(); validatable.error(e); } } catch(Exception e) { }
  • 122. ScriptEngineManager m = new ScriptEngineManager(); ScriptEngine nashorn = m.getEngineByName("nashorn"); nashorn.put("age", validatable.getValue()); String js = "age >= 18"; try { Object result = nashorn.eval(js); if(!((Boolean)result) { ValidationError e = new ValidationError(); validatable.error(e); } } catch(Exception e) { }
  • 123. ScriptEngineManager m = new ScriptEngineManager(); ScriptEngine nashorn = m.getEngineByName("nashorn"); nashorn.put("age", validatable.getValue()); String js = "age >= 18"; try { Object result = nashorn.eval(js); if(!((Boolean)result) { ValidationError e = new ValidationError(); validatable.error(e); } } catch(Exception e) { }
  • 124. ScriptEngineManager m = new ScriptEngineManager(); ScriptEngine nashorn = m.getEngineByName("nashorn"); nashorn.put("age", validatable.getValue()); String js = "age >= 18"; Object result = nashorn.eval(js); try { if(!((Boolean)result) { ValidationError e = new ValidationError(); validatable.error(e); } } catch(Exception e) { }
  • 125. ScriptEngineManager m = new ScriptEngineManager(); ScriptEngine nashorn = m.getEngineByName("nashorn"); nashorn.put("age", validatable.getValue()); String js = "age >= 18"; Object result = nashorn.eval(js); if(!((Boolean)result) { ValidationError e = new ValidationError(); validatable.error(e); } try { } catch(Exception e) { }
  • 126. ScriptEngineManager m = new ScriptEngineManager(); ScriptEngine nashorn = m.getEngineByName("nashorn"); nashorn.put("age", validatable.getValue()); String js = "age >= 18"; try { Object result = nashorn.eval(js); if(!((Boolean)result) { ValidationError e = new ValidationError(); validatable.error(e); } } catch (Exception e) { }
  • 130. feb mar nov 6.14 6.15 7.0-M1 7.0-M2 6.18 7.0-M4 2014 jan 6.19 7.0-RC
  • 131. feb mar may 7.0? 7.1? 7.5? 8.0-M1? 2015 jun 7.6? 8.0-M2?
  • 132. Is there a future for server-side frameworks?
  • 133.
  • 134. “We continue to see teams run into trouble using JSF -- JavaServer Faces -- and are recommending you avoid this technology.” –ThoughtWorks Technology Radar January 2014
  • 135. “We continue to see teams run into trouble using JSF -- JavaServer Faces -- and are recommending you avoid this technology. Teams seem to choose JSF because it is a J2EE standard without really evaluating whether the programming model suits them. We think JSF is flawed because it tries to abstract away HTML, CSS and HTTP, exactly the reverse of what modern web frameworks do. JSF, like ASP.NET webforms, attempts to create statefulness on top of the stateless protocol HTTP and ends up causing a whole host of problems involving shared server-side state. We are aware of the improvements in JSF 2.0, but think the model is fundamentally broken. We recommend teams use simple frameworks and embrace and understand web technologies including HTTP, HTML and CSS.” –ThoughtWorks Technology Radar January 2014
  • 136. “We continue to see teams run into trouble using JSF and are recommending you avoid this technology. We think JSF is flawed because it tries to abstract away HTML, CSS and HTTP. JSF, like ASP.NET webforms, attempts to create statefulness on top of the stateless protocol HTTP. We think the model is fundamentally broken.” –ThoughtWorks Technology Radar January 2014
  • 137. “We continue to see teams run into trouble using JSF and are recommending you avoid this technology. We think JSF is flawed because it tries to abstract away HTML, CSS and HTTP. JSF, like ASP.NET webforms, attempts to create statefulness on top of the stateless protocol HTTP. We think the model is fundamentally broken.” –ThoughtWorks Technology Radar January 2014
  • 138. “We recommend teams use simple frameworks and embrace and understand web technologies including HTTP, HTML and CSS.”
  • 139. JavaScript Frameworks War JQuery AngularJS Ember.js React Backbone.js Meteor KnockoutJS Dojo Agility.js CanJS Polymer Mithril Ampersand Maria Flight Knockback.js
  • 140. What is the Future for web development?
  • 141. What is the Future for web development? Web Components
  • 142. What is the Future for web development? Web Components AngularJS Polymer (2.0)
  • 143. What is the Future of Wicket?
  • 144. a brief history of Wicket the current state of Wicket the future of Wicket Summary