Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Wicket 10 years and beyond

1,573 views

Published on

With the Tenth Anniversary of Wicket behind us, Wicket is still one of the thriving survivors of the Great Web Framework Wars of the mid 00's. Is there a future for server-side frameworks? In this presentation Martijn Dashorst provides a brief history of Wicket.

With a State of the Wicket, Martijn will look at who is currently using Wicket, the community and current release plans.

The majority of this session will be dedicated to the future of Wicket: does a component oriented, Java web framework have a future in the era of native clients and client side JavaScript frameworks? Martijn will layout the plans of making Wicket more productive for current users, on integrating better with JavaEE technologies and much more.

Published in: Software
  • Login to see the comments

Wicket 10 years and beyond

  1. 1. Apache Wicket
 10 years and beyond Martijn Dashorst
 topicus onderwijs @dashorst APACHE WICKET
  2. 2. a brief history
 of Wicket the current state
 of Wicket the future
 of Wicket
  3. 3. co-author
  4. 4. 10 year contributor to Wicket
  5. 5. started in 2004 at topicus without any knowledge of web programming
  6. 6. before Wicket at topicus
  7. 7. 2004
  8. 8. using maverick velocity hibernate jasperreports
  9. 9. lots of XML configuration
  10. 10. 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>
  11. 11. high learning curve
  12. 12. no back button support no multi-tab support
  13. 13. HTTP Session dumping ground
  14. 14. 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))
  15. 15. complex UI neigh impossible
  16. 16. a framework that makes reuse possible, minimises configuration, server side state management easy and is as type safe as possible
  17. 17. 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
  18. 18. 120+ java web frameworks
  19. 19. 18 August 2004
  20. 20. 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));
 }
 });
 }
 }
  21. 21. a framework that makes reuse possible, minimises configuration, server side state management easy and is as type safe as possible ✓ ✓ ✓ ✓
  22. 22. 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
  23. 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. 24. 15 java web frameworks alive i.e. made any release in the last year
  25. 25. including Wicket!
  26. 26. 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]
  27. 27. A brief history of Wicket
  28. 28. 2004
  29. 29. 2004 The Server Side
  30. 30. 20052004 codehaus.org The Server Side
  31. 31. 20052004 codehaus.org The Server Side
  32. 32. codehaus.org 2004 The Server Side JavaOne 1.0 1.1 2006 1.2 2005 AJAX
  33. 33. 2007
  34. 34. 2007 1.3 2008
  35. 35. 2007 1.3 2008 2009 1.4 2010 2011 1.5
  36. 36. 2007 1.3 2008 2009 1.4 2010 2011 1.5
  37. 37. 2012 6.0 2013 2014 6.12 6.2 6.4 6.6 6.8 6.10 6.1 6.5 6.9 6.11 6.13 7.0.0-M2 6.16 6.14 6.15 7.0.0-M1 6.3 6.7 6.17 7.0.0-M3 7.0.0-M4 6.18
  38. 38. That's of Apache Wicket! 10 years
  39. 39. The state of Wicket
  40. 40. 1. core 2. extensions 3. spring 4. datetime 5. auth-roles
  41. 41. Mailinglist traffic
  42. 42. Commit activity
  43. 43. Meanwhile at devoxx...
  44. 44. 0% 25% 50% 75% 100% REST+JavaScript SpringMVC JavaScriptlibrary JSF+JavaEE GWT Wicket Play Vaadin Strutsv1orv2 Grails ApacheSling WebSockets+JavaScript Spray+AkkaHTTP ZKframework Other
  45. 45. User Manual 195 25 Wicket Internals 25.1 Page storing During request handling, Wicket manages page instances through interface . This interface creates a new page instance ororg.apache.wicket.request.handler.IPageProvider loads a previously serialized page instance if we provide the corrisponding page id. delegatesIPageProvider page creation and retrieval to interface . When pageorg.apache.wicket.request.mapper.IPageSource class is provided delegates page creation to interface ,IPageSource org.apache.wicket.IPageFactory while when page id is provided it uses interface to load theorg.apache.wicket.page.IPageManager previously 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.IPageManager and store their last state in the backing stores, namely . The default implementationIPageStore collects all stateful pages which have been used in theorg.apache.wicket.page.PageStoreManager request cycle (more than one page can be used in a single request if for example orsetResponsePage() is used). At the end of the request all collected page instances are being storedRestartResponseException in 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 andIPageProvider 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 implementation useIPageManager . 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.IPageStore the underlying . The default implementationIDataStore pre-processes the pages before passing them toorg.apache.wicket.pageStore.DefaultPageStore 183 As you can see above, the Exception gets raised during the initialization of the instance evenWicketTester 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: 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 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, 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
  46. 46. 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
  47. 47. The future of Wicket ?
  48. 48. Wicket 1.4 security releases only
  49. 49. Wicket 1.5 security releases only
  50. 50. Wicket 6
  51. 51. java 6
  52. 52. semantic versioning
  53. 53. semi-monthly releases mainly bug fixes some new minor features
  54. 54. Wicket 7
  55. 55. Java 7
  56. 56. Servlet 3
  57. 57. Minor API breaks
  58. 58. Component queuing
  59. 59. public class HomePage extends WebPage { public HomePage() { add(new Label("title", "Hello!")); } }
  60. 60. public class HomePage extends WebPage { public HomePage() { add(new Label("title", "Hello!")); } } <html> <body> <h1 wicket:id="title"></h1> </body> </html>
  61. 61. public class HomePage extends WebPage { public HomePage() { add(new Label("title", "Hello!")); } } <html> <body> <h1 wicket:id="title"></h1> </body> </html>
  62. 62. Add a <div> around content...
  63. 63. <html> <body> <div wicket:id="container"> <h1 wicket:id="title"></h1> </div> </body> </html>
  64. 64. <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!"));} }
  65. 65. <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!"));} }
  66. 66. code always follows markup in Wicket
  67. 67. <html> <body> <div wicket:id="container"> <h1 wicket:id="title"></h1> </div> </body> </html>
  68. 68. 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>
  69. 69. 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>
  70. 70. 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>
  71. 71. code always follows markup in Wicket or does it?
  72. 72. Enter Component Queuing (coming to you in wicket 7)
  73. 73. 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(...));
  74. 74. 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!"));
 }
 }
  75. 75. <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>
  76. 76. Limitations of
 Component Queuing
  77. 77. queue(new Label("label", "Some text"));
 queue(new Label("label", "Other text"));
  78. 78. queue(new Label("label", "Some text"));
 queue(new Label("label", "Other text"));
  79. 79. 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
  80. 80. <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>
  81. 81. <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>
  82. 82. <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">
  83. 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">
 </fieldset> <dt>Card number: <i wicket:id="creditCardNumber">
  84. 84. <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>
  85. 85. <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>
  86. 86. 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
  87. 87. Wicket 8
  88. 88. Java 8
  89. 89. PROJECT LAMBDA “functional” programming in Java
  90. 90. public interface ILinkListener {
 void onLickClicked();
 } ILinkListener l = new ILinkListener(){
 @Override
 public void onLinkClicked() {
 System.out.println("Klik");
 }
 }
  91. 91. public interface ILinkListener {
 void onLickClicked();
 } ILinkListener l = () -> {
 System.out.println("Klik");
 }
  92. 92. ILinkListener l = () -> {
 System.out.println("Klik");
 } ILinkListener l = new ILinkListener(){
 @Override
 public void onLinkClicked() {
 System.out.println("Klik");
 }
 } or
  93. 93. add(new Link<Void>("save") {
 @Override
 public void onClick() {
 dao.save(object);
 getSession().info("Saved.");
 setResponsePage(new OtherPage())
 }
 });
  94. 94. add(new Link<Void>("save") {
 @Override
 public void onClick() {
 dao.save(object);
 getSession().info("Saved.");
 setResponsePage(new OtherPage())
 }
 });
  95. 95. add(new Link<>("save").onClick(()-> {
 dao.save(object);
 getSession().info("Saved.");
 setResponsePage(new OtherPage())
 }); no more type information
  96. 96. private void onSave() {
 dao.save(object);
 getSession().info("Saved.");
 setResponsePage(new OtherPage())
 }

  97. 97. private void onSave() {
 dao.save(object);
 getSession().info("Saved.");
 setResponsePage(new OtherPage())
 }
 add(new Link<Void>("save")
 .onClick(this::onSave));

  98. 98. A link with onclick, visibility and body
  99. 99. add(new Link<Void>("like"));
 

  100. 100. add(new Link<Void>("like") {
 });
  101. 101. add(new Link<Void>("like") {
 @Override
 public void onClick() {
 person.likedBy(me);
 }
 });
  102. 102. add(new Link<Void>("like") {
 @Override
 public void onClick() {
 person.likedBy(me);
 }
 
 @Override
 public boolean isVisible() {
 return person.isNotLiked();
 }
 });
  103. 103. add(new Link<Void>("like") {
 @Override
 public void onClick() {
 person.likedBy(me);
 }
 
 @Override
 public boolean isVisible() {
 return person.isNotLiked();
 }
 }.setBody());
  104. 104. add(new Link<Void>("like") {
 @Override
 public void onClick() {
 person.likedBy(me);
 }
 
 @Override
 public boolean isVisible() {
 return person.isNotLiked();
 }
 }.setBody(new AbstractReadOnlyModel<String>() { 
 }));
  105. 105. 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() {
 } }));
  106. 106. 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();
 } }));
  107. 107. A link with onclick, visibility and body
  108. 108. add(new Link<>("like"));

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

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

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

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

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

  114. 114. 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
  115. 115. nashorn
  116. 116. JavaScript validation
  117. 117. 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) { }
  118. 118. 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) { }
  119. 119. 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) { }
  120. 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. 121. 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) { }
  122. 122. 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) { }
  123. 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. 124. java.time
  125. 125. Schedule
  126. 126. 6.14 6.15 7.0-M1 7.0-M2 7.0-M4 6.18 feb mar nov 2014 7.0-RC 6.19 jan
  127. 127. 7.0? 7.1? 8.0-M1? 7.5? feb mar may 2015 8.0-M2? 7.6? jun
  128. 128. Is there a future for 
 server-side frameworks?
  129. 129. 0% 25% 50% 75% 100% REST+JavaScript SpringMVC JavaScriptlibrary JSF+JavaEE GWT Wicket Play Vaadin Strutsv1orv2 Grails ApacheSling WebSockets+JavaScript Spray+AkkaHTTP ZKframework Other
  130. 130. JavaScript Frameworks War JQuery AngularJS Ember.js React Backbone.js Meteor KnockoutJS Dojo Agility.js CanJS Polymer Mithril Maria Flight Knockback.jsAmpersand
  131. 131. What is the Future for web development?
  132. 132. What is the Future for web development? Web Components
  133. 133. What is the Future for web development? Web Components PolymerAngularJS (2.0)
  134. 134. What is the Future of Wicket?
  135. 135. No Revolution but Evolution
  136. 136. a brief history
 of Wicket the current state
 of Wicket the future
 of Wicket Summary
  137. 137. thank you
  138. 138. Questions?
  139. 139. contact @dashorst topicus stand

×