Your SlideShare is downloading. ×
  • Like
The State of Wicket
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

The State of Wicket

  • 15,242 views
Published

The current state of the Apache Wicket framework in 2014 as presented at the DEVdev meetup held in Deventer, the Netherlands. …

The current state of the Apache Wicket framework in 2014 as presented at the DEVdev meetup held in Deventer, the Netherlands.

- A critique of ThoughtWorks' Technology Review 2014 where they slam JSF (jay) as a concept (nay)
- A look back at 10 years of Wicket
- A review of the current Wicket versions
- An outlook and roadmap for Wicket 7 and Wicket 8

The DEVdev (Deventer Developers) is a new meetup for any developer in the eastern part of the Netherlands (the right side of the IJssel river). This presentation was delivered at the first meetup, and was kindly sponsored by Topicus B.V.

Published in Technology , Education
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
15,242
On SlideShare
0
From Embeds
0
Number of Embeds
15

Actions

Shares
Downloads
42
Comments
0
Likes
5

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. State of 
 Apache Wicket
  • 2. presented at: DEVELOPERS DEV ENTER powered by Topicus
  • 3. sponsored by topicus
  • 4. “We continue to see teams run into trouble using JSF -- JavaServer Faces -- and are recommending you avoid this technology.” –ThoughtWorks Technology Radar January 2014 Wicket Developers Rejoice! ! Our archenemy has been de nounced!! ! Or is there more to this stor y?
  • 5. “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 orks from ThoughtW do. JSF, he full webforms, attempts to create are TASP.NET quote like . stateless od bits HTTP gy Radthe The go protocol echnolo top of ar T statefulness on next s ide .. the a whole lhost.of problems on and ends up causing 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
  • 6. “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 This is not a critique of JSF in part icular but (server side) component framework s. The grunt of the critique is that JSF att empts to create state fullness on top of the stateless protocol–which is precisely what J SF, .Net, Wicket and Tapestry are doing.
  • 7. “We recommend teams use simple frameworks and embrace and understand web technologies including HTTP, HTML and CSS.” –ThoughtWorks Technology Radar January 2014 with this assessment:! I don’t agree managing frameworks were server side, state solution for problems created to provide a ifficult to solve with “simple that are d frameworks”. ! 2004 is not the solution! Going back to
  • 8. A typical screen in one of our 1000+ pag e multi-tenant SaaS applications.! Would a“simple framework” make it po ssible to maintain 3 of these 1M lines of code applications with just 30 developers?
  • 9. 10 years of Apache Wicket
  • 10. 2004
  • 11. 2004 Wicket is presented to the w or ! ld.! Raise your hand if you still r ead TheServerside.com?
  • 12. 2004 The Server Side
  • 13. 2004 The orig The Server Side inal Wicket website. We have seen several different stylings ov er the years...
  • 14. 2004 2005 codehaus.org The Server Side
  • 15. 2004 2005 codehaus.org The Server Side icket meetup in 2005 in The first W r at the Topicus offices. Devente
  • 16. 2004 2005 codehaus.org The Server Side
  • 17. 2004 2005 JSF Wicket Tapestry codehaus.org The Server Side Struts 2 (originally Webwork) The web framework sh oot-out at JavaOne 2005. Now th at was fun! Shale
  • 18. 2004 2005 codehaus.org The Server Side JavaOne
  • 19. 2004 2005 codehaus.org 1.0 The Server Side JavaOne
  • 20. 2004 2005 codehaus.org The Server Side 1.0 1.1 JavaOne
  • 21. 2004 2005 codehaus.org The Server Side 1.0 1.1 JavaOne 2006 1.2
  • 22. 2007
  • 23. 2007 Wicket joins ! The Apache Software Foundation!
  • 24. 2007 ket meetups in One of 3 Wic rganised by Arjé Amsterdam o hn (Hippo CMS) Ca
  • 25. 2007
  • 26. 2007 2008 1.3
  • 27. 2007 2008 1.3
  • 28. 2007 2008 1.3
  • 29. 2007 2008 2009 1.3 1.4
  • 30. 2007 2008 2009 2010 1.3 1.4
  • 31. 2007 2008 2009 2010 2011 1.3 1.4 1.5
  • 32. 2012 2013 2014
  • 33. 2012 2013 6.0 2014
  • 34. 2012 2013 2014 6.2 6.6 6.10 6.0 6.4 6.8 6.12 6.1 6.5 6.9 6.13 6.3 6.7 6.11
  • 35. State of Apache Wicket
  • 36. 1. core 2. extensions 3. spring 4. datetime 5. auth-roles
  • 37. Mailinglist traffic
  • 38. Commit activity Wicket in Action Wicket Cookbook
  • 39. Commit activity Wicket in Action Wicket Cookbook e a dent used quit ng has ca tivities:! book writi related ac ur Wicket in o ajor part. plays a m burn-out
  • 40. In a Nutshell, Wicket... – Ohloh report for Wicket
  • 41. In a Nutshell, Wicket... … has had 17,645 commits made by 52 contributors representing 314,959 lines of code – Ohloh report for Wicket
  • 42. In a Nutshell, Wicket... … has had 17,645 commits made by 52 contributors representing 314,959 lines of code … is mostly written in Java with
 a well-commented source code – Ohloh report for Wicket
  • 43. In a Nutshell, Wicket... … has had 17,645 commits made by 52 contributors representing 314,959 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 – Ohloh report for Wicket
  • 44. In a Nutshell, Wicket... … has had 17,645 commits made by 52 contributors representing 314,959 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 83 years of effort (COCOMO model)
 starting with its first commit in September, 2004
 ending with its most recent commit 2 days ago – Ohloh report for Wicket
  • 45. Wicket 1.4 rity fixes only secu
  • 46. Wicket 1.5 rity fixes only secu
  • 47. Wicket 6 released along continues to be , monthlies will side Wicket 7 onthlies when nsform into bi-m tra resolved tickets number of subsides.
  • 48. Java 6
  • 49. semantic versioning Works wonderful for us. Only snag: JQuery updates.
  • 50. Monthly releases also wonderful: no longer waiting for a long time for a fixed bug.
  • 51. Wicket 7 ch to say about Wicket 7: not mu no major API changes.
  • 52. Java 7
  • 53. Servlet 3
  • 54. Minor API breaks
  • 55. Wicket 8 Anything written here is just speculation from my side. This is not set in stone, this is not how e are going to implement things, w or quite reasonably at all.
  • 56. Java 8
  • 57. PROJECT LAMBDA “functional” programming in Java
  • 58. @FunctionalInterface public interface ILinkListener { void onLickClicked(); }
  • 59. ILinkListener l = new ILinkListener() { @Override public void onLinkClicked() { System.out.println("Klik"); } }
  • 60. ILinkListener l = () -> { System.out.println("Klik"); }
  • 61. ILinkListener l = new ILinkListener() { @Override public void onLinkClicked() { System.out.println("Klik"); } } -of! ILinkListener l = () -> { System.out.println("Klik"); }
  • 62. add(new Link<Void>("save") { @Override public void onClick() { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage()) } });
  • 63. add(new Link<Void>("save") { @Override public void onClick() { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage()) } });
  • 64. add(new Link<>("save").onClick(()-> { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage()); });
  • 65. private void onSave() { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage()) } ! ! ! ! ! !
  • 66. private void onSave() { dao.save(object); getSession().info("Saved."); setResponsePage(new OtherPage()) } ! ! add(new Link<Void>("save") .onClick(this::onSave); ! !
  • 67. A link with onclick, visibility and body
  • 68. 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(); } }));
  • 69. 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(); } }));
  • 70. 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(); } }));
  • 71. 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(); } }));
  • 72. 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(); } }));
  • 73. 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(); } }));
  • 74. 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(); } }));
  • 75. A link with onclick, visibility and body
  • 76. add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) .body(() -> { StringBuilder sb = new StringBuilder("L sb.append(person.getFirstName()); return sb.toString(); }) );
  • 77. add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) .body(() -> { StringBuilder sb = new StringBuilder("L sb.append(person.getFirstName()); return sb.toString(); }) );
  • 78. add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) .body(() -> { StringBuilder sb = new StringBuilder("L sb.append(person.getFirstName()); return sb.toString(); }) );
  • 79. add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) .body(() -> { StringBuilder sb = new StringBuilder("L sb.append(person.getFirstName()); return sb.toString(); }) );
  • 80. add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) .body(() -> { StringBuilder sb = new StringBuilder("L sb.append(person.getFirstName()); return sb.toString(); }) );
  • 81. add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) .body(() -> { StringBuilder sb = new StringBuilder("L sb.append(person.getFirstName()); return sb.toString(); }) );
  • 82. 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(); } })); add(new Link<>("like") .visible(() -> person.isNotLiked()) .onClick(() -> person.likedBy(me)) .body(() -> { StringBuilder sb = new StringBuilder("L sb.append(person.getFirstName()); return sb.toString(); }) ); ! ! ! ! ! ! ! ! Anon inner classes: 17 lines Java 8 lambdas: 9 lines
  • 83. nashorn
  • 84. JavaScript validation
  • 85. 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) { }
  • 86. 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) { }
  • 87. 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) { }
  • 88. 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) { }
  • 89. 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) { }
  • 90. 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) { }
  • 91. 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) { }
  • 92. ScriptEngineManager m = ! ScriptEngine nashorn = m.getEngineByName( ! nashorn.put( was only a proof-of-concept This . String js =is probably won Th ’t ever fly due ! to business entities residing on try server, and difficult to share those Object result = nashorn.eval(js); in browser, including I18N m e = new ValidationErroressages. ValidationError() } } } validatable.error(e);
  • 93. java.time support for this will be for converters, validations and possibly wicket-datetime
  • 94. Roadmap Anything written here is just speculation from my side. This is not set in stone. Dates are mere guidelines.
  • 95. Monthly releases
  • 96. 2014 feb mar may 6.1 4 6.1 6.1 -M 7.0 7.0 1 5 -M 2 jun 8 7.0 6.1 9 7.1
  • 97. 2015 feb mar 7.1 7.9 8.0 -M 1 may 7.1 8.0 0 -M 2 jun 2 8.0 7.1 3 8.1
  • 98. git organization
  • 99. master wicket-1.0.x wicket-1.1.x wicket-1.2.x wicket-1.3.x wicket-1.4.x wicket-1.5.x wicket-6.x ! Current organisation of our repository: master is new development, rest is maintenance.
  • 100. master wicket-1.0.x wicket-1.1.x wicket-1.2.x wicket-1.3.x wicket-1.4.x wicket-1.5.x wicket-6.x ! x! cket 7. wi Current organisation of our repository: master is new development, rest is maintenance.
  • 101. master wicket-1.0.x wicket-1.1.x wicket-1.2.x wicket-1.3.x wicket-1.4.x wicket-1.5.x wicket-6.x wicket-7.x wicket-8.x proposed layout: no more master, but just product branches.
  • 102. experimental modules Jay! Many exper imental modules have been upgra ded to core modules! beanva lidation, CDI-1.1, web sockets will be part of Wicket core from 6.14 an d onwards.
  • 103. org.apache.wicket.experimental.wicket-6.x wicket-atmosphere wicket-bootstrap wicket-new-examples ! org.apache.wicket.experimental.wicket-7.x Remaining wicket-atmosphere experimental modules wicket-cdi-1.1
  • 104. org.apache.wicket.experimental.wicket-6.x wicket-atmosphere wicket-bootstrap wicket-new-examples ! tstrap: bootstrap is No more boo org.apache.wicket.experimental.wicket-7.x new examples: ource reference to no just a res wicket-atmosphere r time to do anyth CSS. Write you t and ing JavaScrip wicket-cdi-1.1 use useful with them 0 lines of code) or . own (~1 ’s bootstrap wicket L0rdn1kk0n component library.
  • 105. Wicket 6.x org.apache.wicket.experimental.wicket-6.x wicket-atmosphere ! Wicket 7.x ! org.apache.wicket.experimental.wicket-7.x wicket-atmosphere ! How to separate the same experimental modules in multiple product lines?
  • 106. Wicket 6.x org.apache.wicket.experimental.wicket-6.x wicket-atmosphere ! Wicket 7.x ! org.apache.wicket.experimental.wicket-7.x wicket-atmosphere ! Make the groupId specific to the product line, keep code as sim ilar as possible.
  • 107. The state of Apache Wicket:
  • 108. The state of Apache Wicket: HEALTHY
  • 109. DEVELOPERS DEV ENTER powered by Topicus