wicket 10 years and beyond

143
Apache Wicket 10 years and beyond Martijn Dashorst topicus onderwijs @dashorst APACHE WICKET

Upload: martijn-dashorst

Post on 15-Jul-2015

150 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Wicket   10 years and beyond

Apache Wicket10 years and beyond

Martijn Dashorsttopicus onderwijs @dashorst

APACHE WICKET

Page 2: Wicket   10 years and beyond

a brief history of Wicket

the current stateof Wicket

the futureof Wicket

Page 3: Wicket   10 years and beyond

co-author

Page 4: Wicket   10 years and beyond

10 year contributor to Wicket

Page 5: Wicket   10 years and beyond

started in 2004 at topicuswithout any knowledge of web programming

Page 6: Wicket   10 years and beyond

before Wicketat topicus

Page 7: Wicket   10 years and beyond

2004

Page 8: Wicket   10 years and beyond

using maverick velocity hibernate jasperreports

Page 9: Wicket   10 years and beyond

lots of XML configuration

Page 10: Wicket   10 years and beyond

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>

Page 11: Wicket   10 years and beyond

high learning curve

Page 12: Wicket   10 years and beyond

no back button support no multi-tab support

Page 13: Wicket   10 years and beyond

HTTP Session dumping ground

Page 14: Wicket   10 years and beyond

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

Page 15: Wicket   10 years and beyond

complex UI neigh impossible

Page 16: Wicket   10 years and beyond

a framework that makes reuse possible, minimises configuration, server side state management easy and is as type safe as possible

Page 17: Wicket   10 years and beyond

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

Page 18: Wicket   10 years and beyond

120+ java web frameworks

Page 19: Wicket   10 years and beyond

18 August 2004

Page 20: Wicket   10 years and beyond

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

Page 21: Wicket   10 years and beyond

a framework that makes reuse possible, minimises configuration, server side state management easy and is as type safe as possible

✓ ✓

✓✓

Page 22: Wicket   10 years and beyond

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

Page 23: Wicket   10 years and beyond

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

Page 24: Wicket   10 years and beyond

15 java web frameworks alivei.e. made any release in the last year

Page 25: Wicket   10 years and beyond

including Wicket!

Page 26: Wicket   10 years and beyond

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]

Page 27: Wicket   10 years and beyond

A brief history of Wicket

Page 28: Wicket   10 years and beyond

2004

Page 29: Wicket   10 years and beyond

2004

The Server Side

Page 30: Wicket   10 years and beyond

20052004

codehaus.org

The Server Side

Page 31: Wicket   10 years and beyond

20052004

codehaus.org

The Server Side

Page 32: Wicket   10 years and beyond

codehaus.org

2004

The Server Side JavaOne

1.0

1.1

2006

1.2

2005

AJAX

Page 33: Wicket   10 years and beyond

2007

Page 34: Wicket   10 years and beyond

2007

1.3

2008

Page 35: Wicket   10 years and beyond

2007

1.3

2008 2009

1.4

2010 2011

1.5

Page 36: Wicket   10 years and beyond

2007

1.3

2008 2009

1.4

2010 2011

1.5

Page 37: Wicket   10 years and beyond

2012

6.0

2013 2014

6.12

6.2

6.4

6.6

6.8

6.10

6.1 6.5 6.96.11

6.13

7.0.0-M2

6.16

6.14

6.15 7.0.0-M1

6.3 6.76.17 7.0.0-M3

7.0.0-M4

6.18

Page 38: Wicket   10 years and beyond

That's of Apache Wicket!

10 years

Page 39: Wicket   10 years and beyond

The state of Wicket

Page 40: Wicket   10 years and beyond

1. core

2. extensions

3. spring

4. datetime

5. auth-roles

Page 41: Wicket   10 years and beyond

Mailinglist traffic

Page 42: Wicket   10 years and beyond

Commit activity

Page 43: Wicket   10 years and beyond

Meanwhile at devoxx...

Page 44: Wicket   10 years and beyond

0%

25%

50%

75%

100%R

EST+

Java

Scrip

t

Sprin

g M

VC

Java

Scrip

t lib

rary

JSF+

Java

EE

GW

T

Wic

ket

Play

Vaad

in

Stru

ts v

1 or

v2

Gra

ils

Apac

he S

ling

Web

Sock

ets+

Java

Scrip

t

Spra

y+Ak

kaH

TTP

ZK fr

amew

ork

Oth

er

Page 45: Wicket   10 years and beyond

User Manual

195

25 Wicket Internals

25.1 Page storingDuring request handling, Wicket manages page instances through interface

. This interface creates a new page instance ororg.apache.wicket.request.handler.IPageProviderloads a previously serialized page instance if we provide the corrisponding page id. delegatesIPageProviderpage creation and retrieval to interface . When pageorg.apache.wicket.request.mapper.IPageSourceclass is provided delegates page creation to interface ,IPageSource org.apache.wicket.IPageFactorywhile when page id is provided it uses interface to load theorg.apache.wicket.page.IPageManagerpreviously serialized page.

The following workflow diagram summarizes the mechanism seen so far:

IPageManager

's task is to manage which pages have been used in a requestorg.apache.wicket.page.IPageManagerand store their last state in the backing stores, namely . The default implementation IPageStore

collects all stateful pages which have been used in theorg.apache.wicket.page.PageStoreManagerrequest cycle (more than one page can be used in a single request if for example or setResponsePage()

is used). At the end of the request all collected page instances are being storedRestartResponseExceptionin the first level cache - http session. They are stored in http session attribute named

and passed to the underlying "wicket:persistentPageManagerData-APPLICATION_NAME" IPageStore. When the next http request comes will ask for page with specific id and IPageProvider PageStoreManagerwill look first in the http session and if no match is found then it will delegate to the IPageStore. At the end of thesecond request the http session based cache is being overwritten completely with the newly used pageinstances.

To se tup ano ther imp lementa t ion use IPageManager. Theorg.apache.wicket.Application.setPageManagerProvider(IPageManagerProvider)

custom implementation may or may not use .IPageManager IPageStore/IDataStore

IPageStore

's role is to mediate the storing and loading of pages done byorg.apache.wicket.pageStore.IPageStorethe under ly ing . The defaul t implementat ion IDataStore

pre-processes the pages before passing them to org.apache.wicket.pageStore.DefaultPageStore

183

As you can see above, the Exception gets raised during the initialization of the instance evenWicketTesterbefore the actual test method gets executed. Even though we have applied rather cool and simple annotationbased test configuration already described and passed in perfectly well prepared ApplicationContext instance tothe WicketTester instance in the constructor, somewhere down the rabbit hole someone complained that noWebApplicationContext instance could have been found which seems to be required in order to initialize theWicketTester properly.

The problem that we run against here is due to the fact that SpringComponentInjector during its own initializationis trying to get hold of an according Spring's ApplicationContext instance that would normally be there in aruntime 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 ofApplicationContext out of the ServletContext which is perfectly fine for a runtime environment but is unfortunatelyfailing in a test environment:

public WebApplicationContext getRequiredWebApplicationContext(ServletContext sc)static IllegalStateException {throws

WebApplicationContext wac = getWebApplicationContext(sc); (wac == ) {if null IllegalStateException(throw new "No WebApplicationContext found: no

);ContextLoaderListener registered?" } wac;return}

If you still remember we defined a ContextLoaderListener in our web.xml file as part of the configuration of ourruntime environment that makes sure an according WebApplicationContext instance gets initialized andregistered against the ServletContext properly. Luckily, this problem can easily be solved if we slightly changethe way we initialize SpringComponentInjector in our main MyWebApplication class. Apart from the constructorthat we have used so far, there is another constructor in the SpringComponentInjector class that expects thecaller to provide it with an according ApplicationContext instance rather than trying to resolve one on its own:

public SpringComponentInjector(WebApplication webapp, ApplicationContext ctx, wrapInProxies)boolean{ (webapp == )if null { IllegalArgumentException( );throw new "Argument [[webapp]] cannot be "null }

(ctx == )if null { IllegalArgumentException( );throw new "Argument [[ctx]] cannot be "null }

// store context in application's metadata … webapp.setMetaData(CONTEXT_KEY, ApplicationContextHolder(ctx));new

// … and create and register the annotation aware injector InjectorHolder.setInjector( AnnotSpringInjector( ContextLocator(),new new

Page 46: Wicket   10 years and beyond

In a Nutshell, Wicket...

… has had 18,255 commits made by 62 contributors representing 318,037 lines of code

… is mostly written in Java witha 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, 2004ending with its most recent commit 1 days ago– openhub.net report for Wicket

Page 47: Wicket   10 years and beyond
Page 48: Wicket   10 years and beyond
Page 49: Wicket   10 years and beyond
Page 50: Wicket   10 years and beyond
Page 51: Wicket   10 years and beyond

The future of Wicket ?

Page 52: Wicket   10 years and beyond

Wicket 1.4security releases only

Page 53: Wicket   10 years and beyond

Wicket 1.5security releases only

Page 54: Wicket   10 years and beyond

Wicket 6

Page 55: Wicket   10 years and beyond

java 6

Page 56: Wicket   10 years and beyond

semantic versioning

Page 57: Wicket   10 years and beyond

semi-monthly releases mainly bug fixes some new minor features

Page 58: Wicket   10 years and beyond

Wicket 7

Page 59: Wicket   10 years and beyond

Java 7

Page 60: Wicket   10 years and beyond

Servlet 3

Page 61: Wicket   10 years and beyond

Minor API breaks

Page 62: Wicket   10 years and beyond

Component queuing

Page 63: Wicket   10 years and beyond

public class HomePage extends WebPage {

public HomePage() {

add(new Label("title", "Hello!"));

} }

Page 64: Wicket   10 years and beyond

public class HomePage extends WebPage {

public HomePage() {

add(new Label("title", "Hello!"));

} } <html>

<body> <h1 wicket:id="title"></h1> </body> </html>

Page 65: Wicket   10 years and beyond

public class HomePage extends WebPage {

public HomePage() {

add(new Label("title", "Hello!"));

} } <html>

<body> <h1 wicket:id="title"></h1> </body> </html>

Page 66: Wicket   10 years and beyond

Add a <div> around content...

Page 67: Wicket   10 years and beyond

<html> <body> <div wicket:id="container">

<h1 wicket:id="title"></h1>

</div> </body> </html>

Page 68: Wicket   10 years and beyond

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

Page 69: Wicket   10 years and beyond

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

Page 70: Wicket   10 years and beyond

code always follows markupin Wicket

Page 71: Wicket   10 years and beyond

<html> <body> <div wicket:id="container"> <h1 wicket:id="title"></h1> </div> </body> </html>

Page 72: Wicket   10 years and beyond

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>

Page 73: Wicket   10 years and beyond

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>

Page 74: Wicket   10 years and beyond

public class HomePage extends WebPage { public HomePage() { WebMarkupContainer container = new WebMarkupContainer("container"); add(container); container.add(new Label("title", "Hello!")); } }

<html> <body> <div wicket:id="container"> <h1 wicket:id="title"></h1> </div> </body> </html>

Page 75: Wicket   10 years and beyond

code always follows markupin Wicket

or does it?

Page 76: Wicket   10 years and beyond

Enter Component Queuing(coming to you in wicket 7)

Page 77: Wicket   10 years and beyond

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(...));

Page 78: Wicket   10 years and beyond

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

Page 79: Wicket   10 years and beyond

<html> <body> <header><h1 wicket:id="title"></h1></header> <div wicket:id="container"> ... </div> </body> </html>

<html> <body> <div wicket:id="container"> <h1 wicket:id="title"></h1> </div> </body> </html>

Page 80: Wicket   10 years and beyond

Limitations ofComponent Queuing

Page 81: Wicket   10 years and beyond

queue(new Label("label", "Some text"));queue(new Label("label", "Other text"));

Page 82: Wicket   10 years and beyond

queue(new Label("label", "Some text"));queue(new Label("label", "Other text"));

Page 83: Wicket   10 years and beyond

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

Restrictions of Queuing: Ancestors

Page 84: Wicket   10 years and beyond

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

Page 85: Wicket   10 years and beyond

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

Page 86: Wicket   10 years and beyond

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

Page 87: Wicket   10 years and beyond

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

Page 88: Wicket   10 years and beyond

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

Page 89: Wicket   10 years and beyond

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

Page 90: Wicket   10 years and beyond

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

Page 91: Wicket   10 years and beyond

Wicket 8

Page 92: Wicket   10 years and beyond

Java 8

Page 93: Wicket   10 years and beyond

PROJECT LAMBDA “functional” programming in Java

Page 94: Wicket   10 years and beyond

public interface ILinkListener { void onLickClicked();}

ILinkListener l = new ILinkListener(){ @Override public void onLinkClicked() { System.out.println("Klik"); }}

Page 95: Wicket   10 years and beyond

public interface ILinkListener { void onLickClicked();}

ILinkListener l = () -> { System.out.println("Klik"); }

Page 96: Wicket   10 years and beyond

ILinkListener l = () -> { System.out.println("Klik"); }

ILinkListener l = new ILinkListener(){ @Override public void onLinkClicked() { System.out.println("Klik"); }}

or

Page 97: Wicket   10 years and beyond

add(new Link<Void>("save") { @Override public void onClick() { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage()) }});

Page 98: Wicket   10 years and beyond

add(new Link<Void>("save") { @Override public void onClick() { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage()) }});

Page 99: Wicket   10 years and beyond

add(new Link<>("save").onClick(()-> { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage())});

no more type information

Page 100: Wicket   10 years and beyond

private void onSave() { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage())}

Page 101: Wicket   10 years and beyond

private void onSave() { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage())}

add(new Link<Void>("save") .onClick(this::onSave));

Page 102: Wicket   10 years and beyond

A link with onclick, visibility and body

Page 103: Wicket   10 years and beyond

add(new Link<Void>("like"));

Page 104: Wicket   10 years and beyond

add(new Link<Void>("like") {});

Page 105: Wicket   10 years and beyond

add(new Link<Void>("like") { @Override public void onClick() { person.likedBy(me); }});

Page 106: Wicket   10 years and beyond

add(new Link<Void>("like") { @Override public void onClick() { person.likedBy(me); } @Override public boolean isVisible() { return person.isNotLiked(); }});

Page 107: Wicket   10 years and beyond

add(new Link<Void>("like") { @Override public void onClick() { person.likedBy(me); } @Override public boolean isVisible() { return person.isNotLiked(); }}.setBody());

Page 108: Wicket   10 years and beyond

add(new Link<Void>("like") { @Override public void onClick() { person.likedBy(me); } @Override public boolean isVisible() { return person.isNotLiked(); }}.setBody(new AbstractReadOnlyModel<String>() { }));

Page 109: Wicket   10 years and beyond

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

Page 110: Wicket   10 years and beyond

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

Page 111: Wicket   10 years and beyond

A link with onclick, visibility and body

Page 112: Wicket   10 years and beyond

add(new Link<>("like"));

Page 113: Wicket   10 years and beyond

add(new Link<>("like") );

Page 114: Wicket   10 years and beyond

add(new Link<>("like") .visible(() -> person.isNotLiked()));

Page 115: Wicket   10 years and beyond

add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)));

Page 116: Wicket   10 years and beyond

add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) .body(() -> { }));

Page 117: Wicket   10 years and beyond

add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) .body(() -> { StringBuilder sb = new StringBuilder("Like "); sb.append(person.getFirstName()); return sb.toString(); }));

Page 118: Wicket   10 years and beyond

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

Page 119: Wicket   10 years and beyond

nashorn

Page 120: Wicket   10 years and beyond

JavaScript validation

Page 121: Wicket   10 years and beyond

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

Page 122: Wicket   10 years and beyond

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

Page 123: Wicket   10 years and beyond

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

Page 124: Wicket   10 years and beyond

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

Page 125: Wicket   10 years and beyond

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

Page 126: Wicket   10 years and beyond

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

Page 127: Wicket   10 years and beyond

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

Page 128: Wicket   10 years and beyond

java.time

Page 129: Wicket   10 years and beyond

Schedule

Page 130: Wicket   10 years and beyond

6.14 6.15

7.0-M17.0-M2

7.0-M4

6.18

feb mar nov

2014

7.0-RC

6.19

jan

Page 131: Wicket   10 years and beyond

7.0? 7.1?

8.0-M1?

7.5?

feb mar may

2015

8.0-M2?

7.6?

jun

Page 132: Wicket   10 years and beyond

Is there a future for server-side frameworks?

Page 133: Wicket   10 years and beyond

0%

25%

50%

75%

100%R

EST+

Java

Scrip

t

Sprin

g M

VC

Java

Scrip

t lib

rary

JSF+

Java

EE

GW

T

Wic

ket

Play

Vaad

in

Stru

ts v

1 or

v2

Gra

ils

Apac

he S

ling

Web

Sock

ets+

Java

Scrip

t

Spra

y+Ak

kaH

TTP

ZK fr

amew

ork

Oth

er

Page 134: Wicket   10 years and beyond

JavaScript Frameworks War

JQuery AngularJS Ember.js React

Backbone.js Meteor KnockoutJS Dojo

Agility.js CanJS Polymer Mithril

Maria Flight Knockback.jsAmpersand

Page 135: Wicket   10 years and beyond

What is the Future for web development?

Page 136: Wicket   10 years and beyond

What is the Future for web development?

Web Components

Page 137: Wicket   10 years and beyond

What is the Future for web development?

Web Components

PolymerAngularJS(2.0)

Page 138: Wicket   10 years and beyond

What is the Future of Wicket?

Page 139: Wicket   10 years and beyond

No Revolution but Evolution

Page 140: Wicket   10 years and beyond

a brief history of Wicket

the current stateof Wicket

the futureof Wicket

Summary

Page 141: Wicket   10 years and beyond

thank you

Page 142: Wicket   10 years and beyond

Questions?

Page 143: Wicket   10 years and beyond

contact @dashorst

topicus stand