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 2010

19,662 views

Published on

Presentation about Apache Wicket given at FOSDEM 2011. Apache Wicket is an open source, component oriented Java web framework. This presentation features an introduction to the Wicket framework and showcases some of the new features in the upcoming 1.5 release of Wicket.

Published in: Technology
  • Login to see the comments

Wicket 2010

  1. IntroducingApache WicketMartijn Dashorst
  2. Agenda• Introduction to Apache Wicket• New and noteworthy in 1.5• Questions
  3. Martijn Dashorst• Employee @ Topicus• Chair for Apache Wicket• Committer• Apache Member• Author Wicket in Action
  4. Introduction
  5. Wicket is...a component oriented web frameworkusing just HTML and Java
  6. Apache Wicket• Open Source: ASL 2.0• Created in 2004• Java web framework• Component oriented• http://wicket.apache.org
  7. Who’s using Wicket?
  8. mobile.walmart.com supports three categoriesof devices using the same Java code (only the htmlis (very) different.)Try doing that with JSP. — Joachim Kainz
  9. ... We at Vegas.com have been able to re-purpose our Wicket-based air/hotel searchapplication and purchase/checkout application.This is the new mexico.com. [...]The re-use of components and abstract pageswas tremendous. —Scott Swank, chief architect vegas.com
  10. Just HTML
  11. Sign up formExample from Railscast episode #250
  12. Sign up form
  13. Sign up form <h1>Sign Up</h1> <form> <div class="error_messages"> <h2>Form is invalid</h2> <ul> <li>Some error message</li> </ul> </div> <p> <label for="email">E-Mail</label><br/> <input type="email" id="email" /> </p> <p> <label for="password">Password</label> <input type="password" id="password" /> </p> <p> <label for="confirm">Password confirmat <input type="password" id="confirm" /> </p> <p class="button"><input type="submit" va
  14. Sign up form
  15. Sign up form <h1>Sign Up</h1>      <%= form_for @user do |f| %>     <% if @user.errors.any? %>       <div class="error_messages">         <h2>Form is invalid</h2>         <ul>           <% for message in @user.errors.full             <li><%= message %></li>           <% end %>         </ul>       </div>     <% end %>     <p>       <%= f.label :email %><br />       <%= f.text_field :email %>     </p>     <p>       <%= f.label :password %><br />       <%= f.password_field :password %>     </p>     <p>
  16. Sign up form <h1>Sign Up</h1> <form> <div class="error_messages"> <h2>Form is invalid</h2> <ul> <li>Some error message</li> </ul> </div> <p> <label for="email">E-Mail</label><br/> <input type="email" id="email" /> </p> <p> <label for="password">Password</label> <input type="password" id="password" /> </p> <p> <label for="confirm">Password confirmat <input type="password" id="confirm" /> </p> <p class="button"><input type="submit" va
  17. Sign up form <h1>Sign Up</h1> <form> <div wicket:id="feedback" class="error_me <h2>Form is invalid</h2> <ul> <li>Some error message</li> </ul> </div> <p> <label for="email">E-Mail</label><br/> <input wicket:id="email" type="email" i </p> <p> <label for="password">Password</label> <input wicket:id="password" type="passw </p> <p> <label for="confirm">Password confirmat <input wicket:id="confirm" type="passwo </p> <p class="button"><input type="submit" va
  18. Sign up form <h1>Sign Up</h1> <form> <div wicket:id="feedback" class="error_me <h2>Form is invalid</h2> <ul> <li>Some error message</li> </ul> </div> <p> <label for="email">E-Mail</label><br/> <input wicket:id="email" type="email" i </p> <p> <label for="password">Password</label> <input wicket:id="password" type="passw </p> <p> <label for="confirm">Password confirmat <input wicket:id="confirm" type="passwo </p> <p class="button"><input type="submit" va
  19. <tag wicket:id="foo">Instructs Wicket to work on this tag
  20. Imperative markup <h1>Sign Up</h1>• Used by Ruby on Rails, <%= form_for @user do |f| %>   <% if @user.errors.any? %> JSP, Play, Velocity, ...     <div class="error_messag       <h2>Form is invalid</h•       <ul> Great for web developers         <% for message in @u           <li><%= message %>• Great for hacking on a         <% end %>       </ul> web site     </div>   <% end %>   <p>• Code and markup are     <%= f.label :email %><br     <%= f.text_field :email  not separated   </p>   <p>
  21. Declarative markup <h1>Sign Up</h1>• Used by Wicket, Tapestry, <form wicket:id="form"> <div class="error_message Facelets <p> <label for="email">E-Ma• Great for web designers <input type="email" id= </p> <p>• Go from PSD → HTML → <label for="password">P <input type="password" Page → Component </p> <p> <label for="confirm">Pa• Code and markup are <input type="password" </p> strictly separated <p class="button"><input </form>
  22. Just Java
  23. Sign up form<h1>Sign Up</h1>    <%= form_for @user do |f| %>    <% if @user.errors.any? %>      <div class="error_messages">        <h2>Form is invalid</h2>        <ul>          <% for message in @user.errors.full_messages %>            <li><%= message %></li>          <% end %>        </ul>      </div>    <% end %>    <p>      <%= f.label :email %><br />      <%= f.text_field :email %>    </p>    <p>      <%= f.label :password %><br />      <%= f.password_field :password %>    </p>    <p>      <%= f.label :password_confirmation %>  
  24. Sign up formForm form = new Form("signup") { @Override public void onSubmit() { // ... }}add(form);
  25. Sign up formForm form = new Form("signup") { @Override public void onSubmit() { // ... }}add(form);FeedbackPanel feedback = new FeedbackPanel("feedback");feedback.setVisible(form.hasFeedbackMessages());form.add(feedback);
  26. Sign up formForm form = new Form("signup") { @Override public void onSubmit() { // ... }}add(form);FeedbackPanel feedback = new FeedbackPanel("feedback");feedback.setVisible(form.hasFeedbackMessages());form.add(feedback);form.add(new EmailTextField("email", Model.of("")) .setRequired(true));
  27. Sign up formForm form = new Form("signup") { @Override public void onSubmit() { // ... }}add(form);FeedbackPanel feedback = new FeedbackPanel("feedback");feedback.setVisible(form.hasFeedbackMessages());form.add(feedback);form.add(new EmailTextField("email", Model.of("")) .setRequired(true));form.add(new PasswordField("password", Model.of("")) .setRequired(true));
  28. Sign up formForm form = new Form("signup") { @Override public void onSubmit() { // ... }}add(form);FeedbackPanel feedback = new FeedbackPanel("feedback");feedback.setVisible(form.hasFeedbackMessages());form.add(feedback);form.add(new EmailTextField("email", Model.of("")) .setRequired(true));form.add(new PasswordField("password", Model.of("")) .setRequired(true));form.add(new PasswordField("confirm", Model.of("")) .setRequired(true));
  29. Just Java• No logic in markup• Components are objects (use new and extends)• Use OO techniques in your programming• No XML
  30. Concepts
  31. Components• Manipulate markup• Render content• Receive events (onClick, onSubmit)• Examples: Label, Link, Form, TextField, PagingNavigator, Panel, Page, ClientSideImageMap
  32. Models• Provide data to components• Store data for components• Transform data• Retrieve data from persistent storage• Examples: Model<T>, PropertyModel<T>
  33. Behaviors• Decorator/Adapter for Component• Can manipulate markup of Component• Can receive events (onClick)• Add Ajax functionality to components• Example: AjaxSelfUpdatingTimerBehavior
  34. Getting started
  35. Wicket projects• Apache Wicket • Leg before Wicket (extensions, spring, guice, velocity, etc) (Maven archetypes)• Wicket stuff • Apache Isis (grand collection of projects) (incubating, DDD framework)• Seam for Apache • Jolira Tools Wicket (powers mobile.walmart.com)• WiQuery • Visural Wicket (standalone Wicket components) (JQuery integration library)
  36. Apache Wicket projects• Core • Velocity• Extensions • Auth/Roles• Quick start • JMX• IoC • Dev utils • Spring • Guice • Examples• DateTime
  37. Wicket Stuff projects• progressbar • shiro-security • theme• datatable-autocomplete • gae-initializer • yav• flot • push-jdk-1.5 • maven-support• googlecharts • jasperreports • plugin• scala-extensions • mbeanview • input-events• openlayers • jsr303 • javaee-inject• gmap2 • client-and-server-validation • push• inmethod-grid • multi-text-input • wicket-html5• minis • prototype • wicket-servlet3• phonebook • simile-timeline
  38. Quick start
  39. Quick start
  40. Running quickstart$_
  41. Running quickstart$ mvn -o archetype:generate -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=1.5-SNAPSHOT -DgroupId=com.mycompany -DartifactId=myproject -DarchetypeRepository=https://repository.apache.org/content/repositories/snapshots/ -DinteractiveMode=false _
  42. Running quickstart$ mvn -o archetype:generate -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=1.5-SNAPSHOT -DgroupId=com.mycompany -DartifactId=myproject -DarchetypeRepository=https://repository.apache.org/content/repositories/snapshots/ -DinteractiveMode=false[INFO] Scanning for projects...[INFO] -----------------------------------------------------------[INFO] Building Maven Stub Project (No POM) 1[INFO] -----------------------------------------------------------[INFO] >>> maven-archetype-plugin:2.0:generate (default-cli) >>>[INFO] <<< maven-archetype-plugin:2.0:generate (default-cli) <<<[INFO] --- maven-archetype-plugin:2.0:generate (default-cli) ---[INFO] Generating project in Batch mode[INFO] Archetype defined by properties[INFO] -----------------------------------------------------------[INFO] BUILD SUCCESS[INFO] -----------------------------------------------------------[INFO] Total time: 1.279s[INFO] Finished at: Fri Feb 04 22:04:14 CET 2011[INFO] Final Memory: 9M/81M[INFO] -----------------------------------------------------------
  43. Running quickstart$ mvn jetty:run_
  44. Running quickstart$ mvn jetty:run[INFO] Scanning for projects...[INFO] -----------------------------------------------------------[INFO] Building quickstart 1.0-SNAPSHOT[INFO] -----------------------------------------------------------[INFO] Starting jetty 7.2.2.v20101205 ...2011-02-04 22:04:34.969:INFO::jetty-7.2.2.v201012052011-02-04 22:04:35.198:INFO::No Transaction manager found - if yoINFO - WebXmlFile - web.xml: found filter with naINFO - Application - [wicket.myproject] init: WickINFO - RequestListenerInterface - registered listener interfaceINFO - WebApplication - [wicket.myproject] Started Wi********************************************************************* WARNING: Wicket is running in DEVELOPMENT mode. ****** ^^^^^^^^^^^ ****** Do NOT deploy to your live server(s) without changing this.****** See Application#getConfigurationType() for more information*********************************************************************2011-02-04 22:04:35.464:INFO::Started SelectChannelConnector@0.0.0.0:8080[INFO] Started Jetty Server
  45. Running quickstart
  46. Quick start alternative Leg up • Spring • Guice • JDBC • JPA • Hibernate • Scala http://jweekend.com/dev/LegUp
  47. Want to learn more?
  48. Want to learn more?
  49. Want to learn more?http://wicket.apache.org/learn/books.html
  50. Examples
  51. ExamplesHello, World!
  52. Hello, World!<h1>Hello, World</h1>
  53. Hello, World!<h1>[Replaced text]</h1>
  54. Hello, World!<h1 wicket:id="msg">[Replaced text]</h1>
  55. Hello, World!<h1 wicket:id="msg">[Replaced text]</h1> + add(new Label("msg", "Hello, World!"));
  56. Hello, World!<h1 wicket:id="msg">[Replaced text]</h1> + add(new Label("msg", "Hello, World!")); = <h1>Hello, World!</h1>
  57. ExamplesClick counter
  58. This link has been clicked 123 times
  59. This link has been clicked 123 timesThis link has been clicked 123 times!
  60. This link has been clicked 123 timesThis <a href="#">link</a> has been clicked 123times!
  61. This link has been clicked 123 timesThis <a href="#">link</a> has been clicked<span>123</span> times!
  62. This link has been clicked 123 timesThis <a wicket:id="link" href="#">link</a> has beenclicked <span>123</span> times!
  63. This link has been clicked 123 timesThis <a wicket:id="link" href="#">link</a> has beenclicked<span wicket:id="clicks">123</span> times!
  64. This link has been clicked 123 timesThis <a wicket:id="link" href="#">link</a> has beenclicked<span wicket:id="clicks">123</span> times!
  65. This link has been clicked 123 timespublic class ClickCountPage extends WebPage {}
  66. This link has been clicked 123 timespublic class ClickCountPage extends WebPage { public ClickCountPage() { }}
  67. This link has been clicked 123 timespublic class ClickCountPage extends WebPage { private int clicks = 0; public ClickCountPage() { }}
  68. This link has been clicked 123 timespublic class ClickCountPage extends WebPage { private int clicks = 0; public ClickCountPage() { add(new Link<Void>("link") { public void onClick() { clicks++; } }); }
  69. This link has been clicked 123 timespublic class ClickCountPage extends WebPage { private int clicks = 0; public ClickCountPage() { add(new Link<Void>("link") { ... }); add(new Label("clicks", new PropertyModel<Integer>(this, "clicks"))); }}
  70. Wicket for developers
  71. 2 modes for your appDevelopment and Deployment
  72. Development mode$ mvn jetty:run[INFO] Scanning for projects...[INFO] -----------------------------------------------------------[INFO] Building quickstart 1.0-SNAPSHOT[INFO] -----------------------------------------------------------[INFO] Starting jetty 7.2.2.v20101205 ...2011-02-04 22:04:34.969:INFO::jetty-7.2.2.v201012052011-02-04 22:04:35.198:INFO::No Transaction manager found - if yoINFO - WebXmlFile - web.xml: found filter with naINFO - Application - [wicket.myproject] init: WickINFO - RequestListenerInterface - registered listener interfaceINFO - WebApplication - [wicket.myproject] Started Wi********************************************************************* WARNING: Wicket is running in DEVELOPMENT mode. ***** ^^^^^^^^^^^ ***** Do NOT deploy to your live server(s) without changing this. ***** See Application#getConfigurationType() for more information ********************************************************************2011-02-04 22:04:35.464:INFO::Started SelectChannelConnector@0.0.0.0:8080[INFO] Started Jetty Server
  73. Development mode• exceptional error pages• dynamic markup reloading• no caching• no javascript/css optimizations• discover mistakes early (serialization, missing components, ...)• Wicket debugger visible
  74. Deployment mode• Cache markup resources• No checks• Don’t display stack traces to users• Minimize/compress JavaScript• Don’t generate wicket tags• Wicket debugger not visible
  75. FREE PRO TIP:Don’t perform your performance testsin development mode!
  76. Ajax debugger
  77. Ajax debugger
  78. Ajax envelope<?xml version="1.0" encoding="UTF-8"?><ajax-response> <component id="count2"> <![CDATA[<span wicket:id="count" id="count2">1</span>]]> </component></ajax-response>
  79. Error messageUnable to find component with id countin HomePage.This means that you declaredwicket:id=count in your markup, but thatyou either did not add the component toyour page at all, or that the hierarchy doesnot match.
  80. Error pages
  81. Testing the UI
  82. WicketTester• Test components directly, or their markup• Runs tests without starting server• Ajax testing (server side)• Runs in IDE, ant, maven builds• Achieves high code coverage
  83. Testing Hello, World!@Testpublic void rendersWelcomeMessage() {}
  84. Testing Hello, World!@Testpublic void rendersWelcomeMessage() { WicketTester tester = new WicketTester();}
  85. Testing Hello, World!@Testpublic void rendersWelcomeMessage() { WicketTester tester = new WicketTester(); tester.startPage(HelloWorldPage.class);}
  86. Testing Hello, World!@Testpublic void rendersWelcomeMessage() { WicketTester tester = new WicketTester(); tester.startPage(HelloWorldPage.class); tester.assertLabel("msg", "Hello, World!");}
  87. Testing Click Count@Testpublic void clicksIncreaseCount() {}
  88. Testing Click Count@Testpublic void clicksIncreaseCount() { WicketTester tester = new WicketTester();}
  89. Testing Click Count@Testpublic void clicksIncreaseCount() { WicketTester tester = new WicketTester(); tester.startPage(ClickCountPage.class);}
  90. Testing Click Count@Testpublic void clicksIncreaseCount() { WicketTester tester = new WicketTester(); tester.startPage(ClickCountPage.class); tester.assertModelValue("clicks", 0);}
  91. Testing Click Count@Testpublic void clicksIncreaseCount() { WicketTester tester = new WicketTester(); tester.startPage(ClickCountPage.class); tester.assertModelValue("clicks", 0); tester.clickLink("link");}
  92. Testing Click Count@Testpublic void clicksIncreaseCount() { WicketTester tester = new WicketTester(); tester.startPage(ClickCountPage.class); tester.assertModelValue("clicks", 0); tester.clickLink("link"); tester.assertModelValue("clicks", 1);}
  93. Other test frameworks• PageTest (by Kent Tong)• JDave (BDD framework)
  94. Summary• Widely used• Component oriented• Java• Open Source (ASL 2.0)
  95. What’s new in 1.5?
  96. HTML 5 support
  97. Pre 1.5• Checks for valid markup don’t accept new field types• HTML 5 defines: <input type=”text|email|password|number|date| search|url|...”>
  98. Wicket 1.5• EmailTextField• NumberTextField• UrlTextField• RangeTextField
  99. Improved internals
  100. Split up core library• Old: • wicket.jar
  101. Split up core library• Old: • wicket.jar• New: • wicket-requests.jar • wicket-util.jar • wicket-core.jar
  102. Maven users<dependency> <groupId>org.apache.wicket</groupId> <artifactId>wicket-core</artifactId> <version>1.5-RC1</version></dependency>
  103. Simpler request cycle
  104. Wicket < 1.5• Decoding request and handling in state machine• Debugging ‘interesting’• Designed for flexibility• Served its purpose—took on 4 years of engineering
  105. Wicket 1.5• Request cycle processing completely rewritten• Rendering code has been improved and simplified• URL rendering simplified: now in one place
  106. Wicket < 1.5• Custom request cycle: subclass WebRequestCycle• Problematic with add-ons: • HibernateRequestCycle • SecureRequestCycle • ActivityRequestCycle
  107. New: RequestCycleListenerpublic interface IRequestCycleListener { void onBeginRequest(RequestCycle cycle); void onEndRequest(RequestCycle cycle); void onDetach(RequestCycle cycle); IRequestHandler onException(RequestCycle cycle, Exception ex);}
  108. RequestCycleListenerpublic class SomeWebApplication extends WebApplication { @Override protected void init() { } @Override public Class<? extends Page> getHomePage() { return SomePage.class; }}
  109. RequestCycleListenerpublic class SomeWebApplication extends WebApplication { @Override protected void init() { addRequestCycleListener(new IRequestCycleListener() { public void onBeginRequest() { // do something at the beginning of the request } public void onEndRequest() { // do something at the end of the request } public void onException(Exception ex) { // do something here when theres an exception } }); } @Override public Class<? extends Page> getHomePage() { return SomePage.class; }}
  110. Switching to HTTPS
  111. Switching to HTTPSpublic SecurePage extends WebPage { ...}public MyApplications extends WebApplication { @Override public void init() { super.init(); }}
  112. Switching to HTTPS@RequireHttpspublic SecurePage extends WebPage { ...}public MyApplications extends WebApplication { @Override public void init() { super.init(); }}
  113. Switching to HTTPS@RequireHttpspublic SecurePage extends WebPage { ...}public MyApplications extends WebApplication { @Override public void init() { super.init(); setRootRequestMapper( new HttpsMapper(getRootRequestMapper(), new HttpsConfig()); }}
  114. Component event bus
  115. Component event bus• IEventSource: objects that send events <T> void send(IEventSink sink, Broadcast broadcast, T payload);• IEventSink: objects that receive events void onEvent(IEvent<?> event);• Participants: Components, RequestCycle, Session and Application
  116. Event bus exampleAjax link counter
  117. This link has been clicked 123 timespublic class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new Link<Void>("link") { @Override public void onClick() { count++; } }); add(new Label("clicks", new PropertyModel<Integer>(this, "clicks"))); }}
  118. This link has been clicked 123 timespublic class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new Link<Void>("link") { @Override public void onClick() { count++; } }); add(new Label("clicks", new PropertyModel<Integer>(this, "clicks")) .setOutputMarkupId(true)); }}
  119. This link has been clicked 123 timespublic class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new AjaxLink<Void>("link") { @Override public void onClick(AjaxRequestTarget target) { count++; } }); add(new Label("clicks", new PropertyModel<Integer>(this, "clicks")) .setOutputMarkupId(true)); }}
  120. This link has been clicked 123 timespublic class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new AjaxLink<Void>("link") { @Override public void onClick(AjaxRequestTarget target) { count++; target.add(getPage().get("count")); } }); add(new Label("count", new PropertyModel<Integer>(this, "clicks")) .setOutputMarkupId(true)); }}
  121. This link has been clicked 123 timespublic class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new AjaxLink<Void>("link") { @Override public void onClick(AjaxRequestTarget target) { count++; target.add(getPage().get("count")); } }); add(new Label("count", new PropertyModel<Integer>(this, "clicks")) .setOutputMarkupId(true)); }}
  122. Pre-event bus• Link needs to know the updatable components• Makes code brittle, hard to maintain• Better: • Let the label refresh itself with each Ajax request
  123. public class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new AjaxLink<Void>("link") { @Override public void onClick(AjaxRequestTarget target) { count++; target.add(getPage().get("count")); } }); add(new Label("count", new PropertyModel<Integer>(this, "clicks")) .setOutputMarkupId(true)); }}
  124. public class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new AjaxLink<Void>("link") { @Override public void onClick(AjaxRequestTarget target) { count++; send(getPage(), Broadcast.BREADTH, target); } }); add(new Label("count", new PropertyModel<Integer>(this, "clicks")) .setOutputMarkupId(true)); }}
  125. public class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new AjaxLink<Void>("link") { @Override public void onClick(AjaxRequestTarget target) { count++; send(getPage(), Broadcast.BREADTH, target); } }); add(new CountLabel("count", new PropertyModel<Integer>(this, }}
  126. public class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new AjaxLink<Void>("link") { ... }); add(new CountLabel("count", new PropertyModel<Integer>(this, } public class CountLabel extends Label { }}
  127. public class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new AjaxLink<Void>("link") { ... }); add(new CountLabel("count", new PropertyModel<Integer>(this, } public class CountLabel extends Label { public CountLabel(String id, IModel<Integer> model) { super(id, model); } }}
  128. public class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new AjaxLink<Void>("link") { ... }); add(new CountLabel("count", new PropertyModel<Integer>(this, } public class CountLabel extends Label { public CountLabel(String id, IModel<Integer> model) { super(id, model); setOutputMarkupId(true); } }}
  129. public class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new AjaxLink<Void>("link") { ... }); add(new CountLabel("count", new PropertyModel<Integer>(this, } public class CountLabel extends Label { public CountLabel(String id, IModel<Integer> model) { super(id, model); setOutputMarkupId(true); } @Override public void onEvent(IEvent<?> event) { super.onEvent(event); } }}
  130. public class ClickCountPage extends WebPage { private int clicks = 0; public ClickCount() { add(new AjaxLink<Void>("link") { ... }); add(new CountLabel("count", new PropertyModel<Integer>(this, } public class CountLabel extends Label { public CountLabel(String id, IModel<Integer> model) { super(id, model); setOutputMarkupId(true); } @Override public void onEvent(IEvent<?> event) { super.onEvent(event); if (event.getPayload() instanceof AjaxRequestTarget) { AjaxRequestTarget target = (AjaxRequestTarget) event.getPayload(); target.add(this); } } }}
  131. Post-event bus• A bit more code• Updates are now completely decoupled• Make the payload type safe and meaningful: no AjaxRequestTarget, but CountEvent• AJAX requests trigger a default event with an AjaxRequestTarget as payload
  132. And much, much more:http://cwiki.apache.org/WICKET/migration-to-wicket15.html
  133. Thank you! Questions? Ask!

×