Wicket 2010

17,777 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
1 Comment
5 Likes
Statistics
Notes
  • this is better
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
17,777
On SlideShare
0
From Embeds
0
Number of Embeds
5,041
Actions
Shares
0
Downloads
0
Comments
1
Likes
5
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • refresher course voor Wicket\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • quickstart, leg before wicket, projecten en boeken\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • - debug mode voor quick turnaround\n - jrebel\n - markup reloading\n - markup/js/css in package structuur\n - development mode: excellente excepties, andere tools voor ontwikkelaars\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • - wicket tester\n - jdave\n - page test (kent tong?)\n - cucumber wicket\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • 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!

    ×