Wicket in Action
Martijn Dashorst
Øredev 2008
Malmö
Martijn Dashorst
Martijn Dashorst
• Employee @ Topicus
• VP Apache Wicket
• Committer
• Apache Member
• Author Wicket in Action
4 Parts
I. Getting started with Wicket
II. Ingredients for your Wicket applications
III. Preparing for the real world
IV. ...
Getting started with
Wicket
Part I
What is Wicket?
What is Wicket?
Apache Wicket is a component oriented
open source web application framework
using just Java and HTML.
Apache Wicket is a component oriented
open source web application framework
using just Java and HTML.
(XML not included)
What does that mean?
“Writing a Wicket app is rather more like writing
an event-based desktop application than a
web application.”
- Michael Po...
Top 5 features
Top 5 features
1. Just Java and HTML™
Top 5 features
1. Just Java and HTML™
2. No XML configuration
Top 5 features
1. Just Java and HTML™
2. No XML configuration
3. Object Oriented Programming for the Web
Top 5 features
1. Just Java and HTML™
2. No XML configuration
3. Object Oriented Programming for the Web
4. Easy custom com...
Top 5 features
1. Just Java and HTML™
2. No XML configuration
3. Object Oriented Programming for the Web
4. Easy custom com...
Just Java™
Just Java™
• Components are objects (just use extends)
• No annotation hunting
• Not managed by the framework (just use ne...
Just Java™
public class EditPersonLink extends Link {
private final Person person;
public EditPersonLink(String id, Person ...
Just Java™
public class EditPersonLink extends Link {
private final Person person;
public EditPersonLink(String id, Person ...
Just Java™
public class EditPersonLink extends Link {
private final Person person;
public EditPersonLink(String id, Person ...
Just HTML™
Just HTML™
• Designer friendly
Just HTML™
• Designer friendly
• No new language to learn
Just HTML™
• Designer friendly
• No new language to learn
• No serverside scripting in markup
Just HTML™
• Designer friendly
• No new language to learn
• No serverside scripting in markup
• Developers won’t $#$#% up ...
Just HTML™
• Designer friendly
• No new language to learn
• No serverside scripting in markup
• Developers won’t $#$#% up ...
Just HTML™
<table>
<tr>
<c:forEach var="item" items="${sessionScope.list}">
<td>
<c:out value="item.name" />
</td>
</c:for...
Just HTML™
<table>
<tr>
<c:forEach var="item" items="${sessionScope.list}">
<td>
<c:out value="item.name" />
</td>
</c:for...
Just HTML™
<h:dataTable value="#{list}" var="item">
<h:column>
<h:outputText value="#{item.name}"/>
</h:column>
</h:dataTa...
Just HTML™
<h:dataTable value="#{list}" var="item">
<h:column>
<h:outputText value="#{item.name}"/>
</h:column>
</h:dataTa...
Just HTML™
<table>
<tr wicket:id="list">
<td wicket:id="firstname">John</td>
<td wicket:id="lastname">Doe</td>
</tr>
</tabl...
♥designers developers
XML?
XML?
No XML
No XML
• Page navigation is done in Java:
setResponsePage(new MyPage());
No XML
• Page navigation is done in Java:
setResponsePage(new MyPage());
• Configuration is done in Java:
protected void in...
Object Oriented Programming
for the web
Wicket is the first truly modern
framework [...] to fully realize
the promise of object oriented
development.
“
”—James McL...
Embrace encapsulation
public class PersonLink extends Link {
private Person person;
public PersonLink(String id, Person p)...
Embrace encapsulation
public class PersonLink extends Link {
private Person person;
public PersonLink(String id, Person p)...
Use the right abstractions
public abstract class PersonEditPanel extends Panel {
public PersonEditPanel(String id, Person ...
Use the right abstractions
public abstract class PersonEditPanel extends Panel {
public PersonEditPanel(String id, Person ...
Easy custom
component creation
just use extends
public class PersonLink extends Link { ... }
public class PersonEditPanel extends Panel { ... }
public class NationalitySe...
Community
The Wicket community is by far the most
vibrant and helpful open source
community that I have been a part of.
—JeremyThome...
Community
• Part of The Apache Software Foundation
“not simply a group of projects sharing a
server, but rather a communit...
Community
• Part of The Apache Software Foundation
• User list: >800 subscribers, 59 messages/day
• Meetups around the wor...
Community Projects
• Wicket Stuff
jquery, dojo, scriptaculous, google maps,
hibernate, minis, prototip, etc.
• databinder....
http://cafepress.com/apachewicket
Some Examples
Hello,World!
Hello,World!
Hello,World!
<h1>Hello,World!</h1>
Hello,World!
<h1>[replaced text]</h1>
Hello,World!
<h1 wicket:id="msg">[replaced text]</h1>
Hello,World!
<h1 wicket:id="msg">[replaced text]</h1>
+
add(new Label("msg", "Hello,World!"))
Hello,World!
<h1 wicket:id="msg">[replaced text]</h1>
+
add(new Label("msg", "Hello,World!"))
=
<h1>Hello, World!</h1>
Hello,World!
<html>
<head>
<title>Home page</title>
</head>
<body>
<h1 wicket:id="msg">Gets replaced</h1>
</body>
</html>
Hello,World!
package com.example;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic...
Click counter
Click counter
This link has been clicked 123 times.
Click counter
This <a href="#">link</a> has been clicked
123 times.
This link has been clicked 123 times.
Click counter
This <a href="#">link</a> has been clicked
<span>123</span> times.
This link has been clicked 123 times.
Click counter
This <a wicket:id="link" href="#">link</a>
has been clicked <span>123</span> times.
This link has been click...
Click counter
This <a wicket:id="link" href="#">link</a> has
been clicked <span wicket:id="clicks">123</
span> times.
This...
Click counter
public class ClickCounter extends WebPage {
}
Click counter
public class ClickCounter extends WebPage {
public ClickCounter() {
}
}
Click counter
public class ClickCounter extends WebPage {
private int clicks = 0;
public ClickCounter() {
}
}
Click counter
public class ClickCounter extends WebPage {
private int clicks = 0;
public ClickCounter() {
add(new Link("li...
Click counter
public class ClickCounter extends WebPage {
private int clicks = 0;
public ClickCounter() {
add(new Link("li...
Ajax Click counter
Ajax Click counter
public class ClickCounter extends WebPage {
private int clicks = 0;
public ClickCounter() {
add(new Lin...
Ajax Click counter
public ClickCounter() {
final Label label = new Label(...);
add(label);
label.setOutputMarkupId(true)
ad...
Ajax Click counter
public ClickCounter() {
final Label label = new Label(...);
add(label);
label.setOutputMarkupId(true)
ad...
The architecture of
Wicket
Handling requests
RequestSessionApplication
cheese store
Mary
John
search 'leerdammer'
browse 'goat cheeses'
place order
Handling requests
decode
request
determine
target
process
events
respond clean up
Handling requests
decode
request
determine
target
process
events
respond
parameters
page
component
version
interface
clean...
Handling requests
decode
request
determine
target
process
events
respond
event listener
ajax listener
page
resource
...
cl...
Handling requests
decode
request
determine
target
process
events
respond
onClick
onSubmit
...
clean up
Handling requests
decode
request
determine
target
process
events
respond
render page
components
resource
redirect
clean up
Handling requests
decode
request
determine
target
process
events
respond clean up
detach
store page
Handling requests
• Access to page is single threaded
• No multithreading issues in UI code
• Session is not single thread...
Ingredients for your
Wicket application
Part II
• Components
• Behaviors
• Models
• Page Composition
4 ingredients
Wicket Components
Components
• Label
• Link
• AjaxLink
• ListView
• Form
• TextField
• DropDownChoice
• Tree
• DataTable
• DatePicker
• Cust...
Component
•Can handle events
(onClick, onSubmit, ...)
•Writes its markup to
the response
•May or may not have
a Model
Comp...
Component
• Component has identifier (wicket:id)
new Label("msg", "Hello,World!");
• Markup has same identifier (wicket:id)
...
Component
• Components can be nested inside one another
<a href="#" wicket:id="link">
<span wicket:id="label">replaced</sp...
Component
• Components can be nested inside one another
<a href="#" wicket:id="link">
<span wicket:id="label">replaced</sp...
Component
• Components can be nested inside one another
<a href="#" wicket:id="link">
<span wicket:id="label">replaced</sp...
Component
• Components can receive events
public class EditPersonForm extends Form {
public EditPersonForm(String id, Pers...
Component
Component
• Can manipulate markup
Component
• Can manipulate markup
• Directly
protected void onComponentTag(ComponentTag tag) {
tag.put("class", "error");
...
Component
• Can manipulate markup
• Directly
protected void onComponentTag(ComponentTag tag) {
tag.put("class", "error");
...
Behaviors
Behaviors are decorators
for components
Behaviors
• Manipulate component tags
• Add JavaScript to components
• Add Ajax behavior to components
Adding JavaScript to a
component
link.add(new AbstractBehavior() {
public void onComponentTag(Component component,
Compone...
Ajax behaviors
Create a Label that changes
color with a click using Ajax
Create a Label that changes
color with a click using Ajax
Create a Label that changes
color with a click using Ajax
Create a Label that changes
color with a click using Ajax
Label label = new Label("label", "Click me");
Label label = new Label("label", "Click me");
label.setOutputMarkupId(true);
Label label = new Label("label", "Click me");
label.setOutputMarkupId(true);
label.add(new AjaxEventBehavior("onclick") {
...
Label label = new Label("label", "Click me");
label.setOutputMarkupId(true);
label.add(new AjaxEventBehavior("onclick") {
...
Label label = new Label("label", "Click me");
label.setOutputMarkupId(true);
label.add(new AjaxEventBehavior("onclick") {
...
Label label = new Label("label", "Click me");
label.setOutputMarkupId(true);
label.add(new AjaxEventBehavior("onclick") {
...
Ajax behaviors
Ajax behaviors
• Can re-render components
target.addComponent(...);
Ajax behaviors
• Can re-render components
target.addComponent(...);
• Can execute JavaScript
target.appendJavaScript("$('f...
Ajax behaviors
• Can re-render components
target.addComponent(...);
• Can execute JavaScript
target.appendJavaScript("$('f...
Ajax behaviors
• Can re-render components
target.addComponent(...);
• Can execute JavaScript
target.appendJavaScript("$('f...
Ajax Components
• Links, Forms, Buttons, CheckBoxes
• Ajax fallback components
• Indicating components
• Tree, DataTable, ...
Understanding models
Component
M
arkup
M
odel
Wicket models allow
components to retrieve and
store data.
Component
M
arkup
M
odel
Models
Controller
View
TextField
Locator
gets
Model
Cheese
cheese.age
gets
sets
Name Gouda
Age 3 months
OK
Cheese Store
re...
Simple Model usage
new Label("name", customer.getName())
new Label("street",
customer.getAddress().getStreet())
newTextFie...
What’s wrong with this?
new Label("street",
customer.getAddress().getStreet())
What’s wrong with this?
new Label("street",
customer.getAddress().getStreet())
• Label isn’t notified of street/address/
cu...
What’s wrong with this?
new Label("street",
customer.getAddress().getStreet())
• Label isn’t notified of street/address/
cu...
PropertyModel usage
new Label("street",
new PropertyModel(customer, "address.street"))
PropertyModel usage
new Label("street",
new PropertyModel(customer, "address.street"))
setModel(new CompoundPropertyModel(...
PropertyModel
+null safe
+dynamic
–not rename safe
Page composition:
creating a consistent layout
BasePage
BasePage
PageWithMenu
BasePage
PageWithMenu
VivamusPage BlanditPage PretiumPage
Java inheritance
public class BasePage extends WebPage {
public BasePage() {
add(new HeaderPanel("header"));
add(new Foote...
Java inheritance
public class PageWithMenu extends BasePage {
public PageWithMenu() {
add(new Menu("menu"));
}
}
Java inheritance
public classVivamusPage extends PageWithMenu {
publicVivamusPage() {
add(new Label("vivamus", "..."));
ad...
Markup inheritance
<html>
<body>
<div id="bd">
<div wicket:id="header"></div>
<wicket:child />
<div wicket:id="footer"></d...
Markup inheritance
<html>
<body>
<div id="bd">
<div wicket:id="header"></div>
<wicket:child />
<div wicket:id="footer"></d...
Markup inheritance
<wicket:extend>
<div wicket:id="menu"></div>
<div id="main">
<wicket:child />
</div>
</wicket:extend>
Markup inheritance
<wicket:extend>
<div wicket:id="menu"></div>
<div id="main">
<wicket:child />
</div>
</wicket:extend>
Markup inheritance
<wicket:extend>
<table>
<tr>
<td wicket:id="name"></td>
<........>
</tr>
</table
</wicket:extend>
Markup inheritance
• Inherit markup from child pages
• Includes <wicket:head> sections
• Works for Panels too
• Very easy ...
Preparing for the real
world
Part III
Integrate with
Spring & Guice
Getting at Spring
public class CheesesPage extends WebPage {
private CheesesDao dao;
public CheesesPage() {
List<Cheese> =...
Getting at Spring
public class CheesesPage extends WebPage {
@SpringBean
private CheesesDao dao;
public CheesesPage() {
Li...
Make Application Spring
aware
protected void init() {
addComponentInstantiationListener(
new SpringComponentInjector(this)...
Make Wicket Guice aware
protected void init() {
addComponentInstantiationListener(
new GuiceComponentInjector(this,
getMod...
Getting at Guice
public class CheesesPage extends WebPage {
private CheesesDao dao;
public CheesesPage() {
List<Cheese> = ...
Getting at Guice
public class CheesesPage extends WebPage {
@Inject
private CheesesDao dao;
public CheesesPage() {
List<Ch...
Putting your application
into production
Test your Wicket
application
WicketTester
• Test components directly, or their markup
• Runs tests without starting server
• Ajax testing (server side)...
HelloWorld test
@Test
public void labelContainsHelloWorld() {
}
HelloWorld test
@Test
public void labelContainsHelloWorld() {
WicketTester tester =
new WicketTester();
}
HelloWorld test
@Test
public void labelContainsHelloWorld() {
WicketTester tester = new WicketTester();
tester.startPage(H...
HelloWorld test
@Test
public void labelContainsHelloWorld() {
WicketTester tester = new WicketTester();
tester.startPage(H...
Link test
@Test
public void countingLinkClickTest() {
}
Link test
@Test
public void countingLinkClickTest() {
WicketTester tester =
new WicketTester();
}
Link test
@Test
public void countingLinkClickTest() {
WicketTester tester = new WicketTester();
tester.startPage(LinkCount...
Link test
@Test
public void countingLinkClickTest() {
WicketTester tester = new WicketTester();
tester.startPage(LinkCount...
Link test
@Test
public void countingLinkClickTest() {
WicketTester tester = new WicketTester();
tester.startPage(LinkCount...
Link test
@Test
public void countingLinkClickTest() {
WicketTester tester = new WicketTester();
tester.startPage(LinkCount...
Navigation test
@Test
public void navigateToSecondPage() {
WicketTester tester = new WicketTester();
tester.startPage(new ...
Navigation test
@Test
public void navigateToSecondPage() {
WicketTester tester = new WicketTester();
tester.startPage(new ...
URL Makeover
UGLY url
http://cheesr.com/shop?wicket:bookmarkablePage=
%3Acom.cheesr.shop.CheeseDetailsPage&cheese=edam
Prettier urls
http://cheesr.com/cheeses?cheese=edam
http://cheesr.com/cheeses/cheese/edam
http://cheesr.com/cheeses/edam
Mount pages for prettiness
mount(new IndexedParamUrlCodingStrategy("cheeses",
CheeseDetailsPage.class));
http://cheesr.com...
Configure for
production
2 configuration modes
1. Development
maximize developer happiness
2. Deployment
maximize end-user happiness
Development mode
• exceptional error pages
• dynamic markup reloading
• no caching
• no javascript/css optimizations
• dis...
Production mode
• Cache markup resources
• No checks
• Don’t display stack traces to users
• Minimize/compress JavaScript
...
Default setting
INFO - WebApplication - [WicketInActionApplication] Started Wicket
version 1.3.0 in
development mode
*****...
Go to production
• System property:
java -Dwicket.configuration=deployment
• Servlet/filter initialization parameter (web.xm...
The future of Wicket
Part IV
• Java 5 all the way
CustomerLink(String id, IModel model)
Wicket 1.4
• Java 5 all the way
CustomerLink(String id, IModel<Customer>)
Wicket 1.4
• Java 5 all the way
CustomerLink(String id, IModel<Customer>)
• Mostly code compatible with Wicket 1.3
Wicket 1.4
• Java 5 all the way
CustomerLink(String id, IModel<Customer>)
• Mostly code compatible with Wicket 1.3
• Improved OSGi aw...
Wicket 1.5
• New Ajax implementation
• Improved unit test support
• Simplified resources
• Improved multi-window support
• ...
More information
• http://wicket.apache.org
• blog: http://wicketinaction.com
• irc: ##wicket @ irc.freenode.net
• User li...
One more thing...
Wicket in Action
• Martijn Dashorst and
Eelco Hillenius
• August, 2008 | 392 pages
• ISBN: 1932394982
• $44.99 Softbound p...
Questions?
Ask!
the first 6 persons asking a question will receive a
free E-Book of Wicket in Action
Thank you
for your attention...
Wicket In Action - oredev2008
Wicket In Action - oredev2008
Wicket In Action - oredev2008
Wicket In Action - oredev2008
Wicket In Action - oredev2008
Wicket In Action - oredev2008
Wicket In Action - oredev2008
Wicket In Action - oredev2008
Wicket In Action - oredev2008
Wicket In Action - oredev2008
Wicket In Action - oredev2008
Upcoming SlideShare
Loading in...5
×

Wicket In Action - oredev2008

4,276

Published on

Wicket in Action is the introduction I gave at the Øredev conference in Malmö, Sweden in November 2008. You'll learn about Wicket, Components, Models, Integrating Spring, Testing, and deploying your Wicket application.

Unfortunately slideshare doesn't work with accented letters in the URL, so I had to change the title.

Published in: Technology, News & Politics
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,276
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Transcript of "Wicket In Action - oredev2008"

  1. 1. Wicket in Action Martijn Dashorst Øredev 2008 Malmö
  2. 2. Martijn Dashorst
  3. 3. Martijn Dashorst • Employee @ Topicus • VP Apache Wicket • Committer • Apache Member • Author Wicket in Action
  4. 4. 4 Parts I. Getting started with Wicket II. Ingredients for your Wicket applications III. Preparing for the real world IV. The future of Wicket
  5. 5. Getting started with Wicket Part I
  6. 6. What is Wicket?
  7. 7. What is Wicket?
  8. 8. Apache Wicket is a component oriented open source web application framework using just Java and HTML.
  9. 9. Apache Wicket is a component oriented open source web application framework using just Java and HTML. (XML not included)
  10. 10. What does that mean?
  11. 11. “Writing a Wicket app is rather more like writing an event-based desktop application than a web application.” - Michael Porter (LShift)
  12. 12. Top 5 features
  13. 13. Top 5 features 1. Just Java and HTML™
  14. 14. Top 5 features 1. Just Java and HTML™ 2. No XML configuration
  15. 15. Top 5 features 1. Just Java and HTML™ 2. No XML configuration 3. Object Oriented Programming for the Web
  16. 16. Top 5 features 1. Just Java and HTML™ 2. No XML configuration 3. Object Oriented Programming for the Web 4. Easy custom component creation
  17. 17. Top 5 features 1. Just Java and HTML™ 2. No XML configuration 3. Object Oriented Programming for the Web 4. Easy custom component creation 5. Community
  18. 18. Just Java™
  19. 19. Just Java™ • Components are objects (just use extends) • No annotation hunting • Not managed by the framework (just use new)
  20. 20. Just Java™ public class EditPersonLink extends Link { private final Person person; public EditPersonLink(String id, Person person) { super(id); this.person = person; } public void onClick() { setResponsePage(new EditPersonPage(person)); } }
  21. 21. Just Java™ public class EditPersonLink extends Link { private final Person person; public EditPersonLink(String id, Person person) { super(id); this.person = person; } public void onClick() { setResponsePage(new EditPersonPage(person)); } }
  22. 22. Just Java™ public class EditPersonLink extends Link { private final Person person; public EditPersonLink(String id, Person person) { super(id); this.person = person; } public void onClick() { setResponsePage(new EditPersonPage(person)); } }
  23. 23. Just HTML™
  24. 24. Just HTML™ • Designer friendly
  25. 25. Just HTML™ • Designer friendly • No new language to learn
  26. 26. Just HTML™ • Designer friendly • No new language to learn • No serverside scripting in markup
  27. 27. Just HTML™ • Designer friendly • No new language to learn • No serverside scripting in markup • Developers won’t $#$#% up your design
  28. 28. Just HTML™ • Designer friendly • No new language to learn • No serverside scripting in markup • Developers won’t $#$#% up your design • Designers won’t $*&#$# up your code
  29. 29. Just HTML™ <table> <tr> <c:forEach var="item" items="${sessionScope.list}"> <td> <c:out value="item.name" /> </td> </c:forEach> </tr> </table>
  30. 30. Just HTML™ <table> <tr> <c:forEach var="item" items="${sessionScope.list}"> <td> <c:out value="item.name" /> </td> </c:forEach> </tr> </table>
  31. 31. Just HTML™ <h:dataTable value="#{list}" var="item"> <h:column> <h:outputText value="#{item.name}"/> </h:column> </h:dataTable>
  32. 32. Just HTML™ <h:dataTable value="#{list}" var="item"> <h:column> <h:outputText value="#{item.name}"/> </h:column> </h:dataTable>
  33. 33. Just HTML™ <table> <tr wicket:id="list"> <td wicket:id="firstname">John</td> <td wicket:id="lastname">Doe</td> </tr> </table>
  34. 34. ♥designers developers
  35. 35. XML?
  36. 36. XML?
  37. 37. No XML
  38. 38. No XML • Page navigation is done in Java: setResponsePage(new MyPage());
  39. 39. No XML • Page navigation is done in Java: setResponsePage(new MyPage()); • Configuration is done in Java: protected void init() { getDebugSettings() .setAjaxDebugModeEnabled(true); }
  40. 40. Object Oriented Programming for the web
  41. 41. Wicket is the first truly modern framework [...] to fully realize the promise of object oriented development. “ ”—James McLaughlin
  42. 42. Embrace encapsulation public class PersonLink extends Link { private Person person; public PersonLink(String id, Person p) { this.person = p; } public void onClick() { person.someOperation(); } }
  43. 43. Embrace encapsulation public class PersonLink extends Link { private Person person; public PersonLink(String id, Person p) { this.person = p; } public void onClick() { person.someOperation(); } }
  44. 44. Use the right abstractions public abstract class PersonEditPanel extends Panel { public PersonEditPanel(String id, Person p) { add(new Button("save") { public void onSubmit() { onSave(person); } }); add(new Button("delete") { ... }); } protected abstract void onSave(Person p); protected abstract void onDelete(Person p); }
  45. 45. Use the right abstractions public abstract class PersonEditPanel extends Panel { public PersonEditPanel(String id, Person p) { add(new Button("save") { public void onSubmit() { onSave(person); } }); add(new Button("delete") { ... }); } protected abstract void onSave(Person p); protected abstract void onDelete(Person p); }
  46. 46. Easy custom component creation
  47. 47. just use extends
  48. 48. public class PersonLink extends Link { ... } public class PersonEditPanel extends Panel { ... } public class NationalitySelect extends DropDownChoice { ... } just use extends
  49. 49. Community
  50. 50. The Wicket community is by far the most vibrant and helpful open source community that I have been a part of. —JeremyThomerson “ ”
  51. 51. Community • Part of The Apache Software Foundation “not simply a group of projects sharing a server, but rather a community of developers and users.”
  52. 52. Community • Part of The Apache Software Foundation • User list: >800 subscribers, 59 messages/day • Meetups around the world • ##wicket on irc.freenode.net
  53. 53. Community Projects • Wicket Stuff jquery, dojo, scriptaculous, google maps, hibernate, minis, prototip, etc. • databinder.net • Wicket Web Beans • Tons of other projects at googlecode, sourceforge, etc.
  54. 54. http://cafepress.com/apachewicket
  55. 55. Some Examples
  56. 56. Hello,World!
  57. 57. Hello,World!
  58. 58. Hello,World! <h1>Hello,World!</h1>
  59. 59. Hello,World! <h1>[replaced text]</h1>
  60. 60. Hello,World! <h1 wicket:id="msg">[replaced text]</h1>
  61. 61. Hello,World! <h1 wicket:id="msg">[replaced text]</h1> + add(new Label("msg", "Hello,World!"))
  62. 62. Hello,World! <h1 wicket:id="msg">[replaced text]</h1> + add(new Label("msg", "Hello,World!")) = <h1>Hello, World!</h1>
  63. 63. Hello,World! <html> <head> <title>Home page</title> </head> <body> <h1 wicket:id="msg">Gets replaced</h1> </body> </html>
  64. 64. Hello,World! package com.example; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.basic.Label; public class HomePage extends WebPage { public HomePage() { add(new Label("msg", "Hello,World!")); } }
  65. 65. Click counter
  66. 66. Click counter This link has been clicked 123 times.
  67. 67. Click counter This <a href="#">link</a> has been clicked 123 times. This link has been clicked 123 times.
  68. 68. Click counter This <a href="#">link</a> has been clicked <span>123</span> times. This link has been clicked 123 times.
  69. 69. Click counter This <a wicket:id="link" href="#">link</a> has been clicked <span>123</span> times. This link has been clicked 123 times.
  70. 70. Click counter This <a wicket:id="link" href="#">link</a> has been clicked <span wicket:id="clicks">123</ span> times. This link has been clicked 123 times.
  71. 71. Click counter public class ClickCounter extends WebPage { }
  72. 72. Click counter public class ClickCounter extends WebPage { public ClickCounter() { } }
  73. 73. Click counter public class ClickCounter extends WebPage { private int clicks = 0; public ClickCounter() { } }
  74. 74. Click counter public class ClickCounter extends WebPage { private int clicks = 0; public ClickCounter() { add(new Link("link") { protected void onClick() { clicks++; } }); } }
  75. 75. Click counter public class ClickCounter extends WebPage { private int clicks = 0; public ClickCounter() { add(new Link("link") { ... }); add(new Label("clicks", new PropertyModel(this, "clicks"))); } }
  76. 76. Ajax Click counter
  77. 77. Ajax Click counter public class ClickCounter extends WebPage { private int clicks = 0; public ClickCounter() { add(new Link("link") { ... }); add(new Label("clicks", new PropertyModel(this, "clicks"))); } }
  78. 78. Ajax Click counter public ClickCounter() { final Label label = new Label(...); add(label); label.setOutputMarkupId(true) add(new Link("link") { public void onClick() { clicks++; } }); }
  79. 79. Ajax Click counter public ClickCounter() { final Label label = new Label(...); add(label); label.setOutputMarkupId(true) add(new AjaxLink("link") { public void onClick(AjaxRequestTarget t) { clicks++; t.addComponent(label); } }); }
  80. 80. The architecture of Wicket
  81. 81. Handling requests RequestSessionApplication cheese store Mary John search 'leerdammer' browse 'goat cheeses' place order
  82. 82. Handling requests decode request determine target process events respond clean up
  83. 83. Handling requests decode request determine target process events respond parameters page component version interface clean up
  84. 84. Handling requests decode request determine target process events respond event listener ajax listener page resource ... clean up
  85. 85. Handling requests decode request determine target process events respond onClick onSubmit ... clean up
  86. 86. Handling requests decode request determine target process events respond render page components resource redirect clean up
  87. 87. Handling requests decode request determine target process events respond clean up detach store page
  88. 88. Handling requests • Access to page is single threaded • No multithreading issues in UI code • Session is not single threaded
  89. 89. Ingredients for your Wicket application Part II
  90. 90. • Components • Behaviors • Models • Page Composition 4 ingredients
  91. 91. Wicket Components
  92. 92. Components • Label • Link • AjaxLink • ListView • Form • TextField • DropDownChoice • Tree • DataTable • DatePicker • CustomerLink • NationalityDropDownChoice • ShoppingCartPanel
  93. 93. Component •Can handle events (onClick, onSubmit, ...) •Writes its markup to the response •May or may not have a Model Component M arkup M odel
  94. 94. Component • Component has identifier (wicket:id) new Label("msg", "Hello,World!"); • Markup has same identifier (wicket:id) <h1 wicket:id="msg">Gets replaced</h1>
  95. 95. Component • Components can be nested inside one another <a href="#" wicket:id="link"> <span wicket:id="label">replaced</span> </a> Link link = new Link("link") {...}; add(link); link.add(new Label("label", "Some text"));
  96. 96. Component • Components can be nested inside one another <a href="#" wicket:id="link"> <span wicket:id="label">replaced</span> </a> Link link = new Link("link") {...}; add(link); link.add(new Label("label", "Some text"));
  97. 97. Component • Components can be nested inside one another <a href="#" wicket:id="link"> <span wicket:id="label">replaced</span> </a> Link link = new Link("link") {...}; add(link); link.add(new Label("label", "Some text"));
  98. 98. Component • Components can receive events public class EditPersonForm extends Form { public EditPersonForm(String id, Person p) { super(id, new Model(p)); } public void onSubmit() { person.save(); setResponsePage(new ListPage()); } }
  99. 99. Component
  100. 100. Component • Can manipulate markup
  101. 101. Component • Can manipulate markup • Directly protected void onComponentTag(ComponentTag tag) { tag.put("class", "error"); } <td class="error">some text</td>
  102. 102. Component • Can manipulate markup • Directly protected void onComponentTag(ComponentTag tag) { tag.put("class", "error"); } <td class="error">some text</td> • With AttributeModifier label.add(new SimpleAttributeModifier("class", "error")); <td class="error">some text</td>
  103. 103. Behaviors
  104. 104. Behaviors are decorators for components
  105. 105. Behaviors • Manipulate component tags • Add JavaScript to components • Add Ajax behavior to components
  106. 106. Adding JavaScript to a component link.add(new AbstractBehavior() { public void onComponentTag(Component component, ComponentTag tag) { tag.put("onclick", "return confirm('Are you sure?');"); } }); <a href="..." onclick="return confirm('Are you sure?');"> Play thermonuclear war </a>
  107. 107. Ajax behaviors
  108. 108. Create a Label that changes color with a click using Ajax
  109. 109. Create a Label that changes color with a click using Ajax
  110. 110. Create a Label that changes color with a click using Ajax
  111. 111. Create a Label that changes color with a click using Ajax
  112. 112. Label label = new Label("label", "Click me");
  113. 113. Label label = new Label("label", "Click me"); label.setOutputMarkupId(true);
  114. 114. Label label = new Label("label", "Click me"); label.setOutputMarkupId(true); label.add(new AjaxEventBehavior("onclick") { });
  115. 115. Label label = new Label("label", "Click me"); label.setOutputMarkupId(true); label.add(new AjaxEventBehavior("onclick") { private boolean isRed = false; protected void onComponentTag(...) { super.onComponentTag(component, tag); if(isRed) { tag.put("style", "color:red"); } } });
  116. 116. Label label = new Label("label", "Click me"); label.setOutputMarkupId(true); label.add(new AjaxEventBehavior("onclick") { private boolean isRed = false; protected void onEvent(AjaxRequestTarget target) { isRed = !isRed; } protected void onComponentTag(...) { super.onComponentTag(component, tag); if(isRed) { tag.put("style", "color:red"); } } });
  117. 117. Label label = new Label("label", "Click me"); label.setOutputMarkupId(true); label.add(new AjaxEventBehavior("onclick") { private boolean isRed = false; protected void onEvent(AjaxRequestTarget target) { isRed = !isRed; target.addComponent(getComponent()); } protected void onComponentTag(...) { super.onComponentTag(component, tag); if(isRed) { tag.put("style", "color:red"); } } });
  118. 118. Ajax behaviors
  119. 119. Ajax behaviors • Can re-render components target.addComponent(...);
  120. 120. Ajax behaviors • Can re-render components target.addComponent(...); • Can execute JavaScript target.appendJavaScript("$('foo').explode();");
  121. 121. Ajax behaviors • Can re-render components target.addComponent(...); • Can execute JavaScript target.appendJavaScript("$('foo').explode();"); • Can throttle the client side events behavior.setThrottleDelay(Duration.seconds(10));
  122. 122. Ajax behaviors • Can re-render components target.addComponent(...); • Can execute JavaScript target.appendJavaScript("$('foo').explode();"); • Can throttle the client side events behavior.setThrottleDelay(Duration.seconds(10)); • Can add new header related resources JavaScript, stylesheets, etc.
  123. 123. Ajax Components • Links, Forms, Buttons, CheckBoxes • Ajax fallback components • Indicating components • Tree, DataTable, PagingNavigator
  124. 124. Understanding models Component M arkup M odel
  125. 125. Wicket models allow components to retrieve and store data. Component M arkup M odel
  126. 126. Models Controller View TextField Locator gets Model Cheese cheese.age gets sets Name Gouda Age 3 months OK Cheese Store receives renders sets IModel
  127. 127. Simple Model usage new Label("name", customer.getName()) new Label("street", customer.getAddress().getStreet()) newTextField("username", new Model("<username>"))
  128. 128. What’s wrong with this? new Label("street", customer.getAddress().getStreet())
  129. 129. What’s wrong with this? new Label("street", customer.getAddress().getStreet()) • Label isn’t notified of street/address/ customer changes
  130. 130. What’s wrong with this? new Label("street", customer.getAddress().getStreet()) • Label isn’t notified of street/address/ customer changes • NullPointerException: customer, address could be null
  131. 131. PropertyModel usage new Label("street", new PropertyModel(customer, "address.street"))
  132. 132. PropertyModel usage new Label("street", new PropertyModel(customer, "address.street")) setModel(new CompoundPropertyModel(customer)); add(new Label("address.street")); add(new Label("address.zipcode")); add(new Label("address.city"));
  133. 133. PropertyModel +null safe +dynamic –not rename safe
  134. 134. Page composition: creating a consistent layout
  135. 135. BasePage
  136. 136. BasePage PageWithMenu
  137. 137. BasePage PageWithMenu VivamusPage BlanditPage PretiumPage
  138. 138. Java inheritance public class BasePage extends WebPage { public BasePage() { add(new HeaderPanel("header")); add(new FooterPanel("footer")); } }
  139. 139. Java inheritance public class PageWithMenu extends BasePage { public PageWithMenu() { add(new Menu("menu")); } }
  140. 140. Java inheritance public classVivamusPage extends PageWithMenu { publicVivamusPage() { add(new Label("vivamus", "...")); add(new Link("link"){...}); } }
  141. 141. Markup inheritance <html> <body> <div id="bd"> <div wicket:id="header"></div> <wicket:child /> <div wicket:id="footer"></div> </div> </body> </html>
  142. 142. Markup inheritance <html> <body> <div id="bd"> <div wicket:id="header"></div> <wicket:child /> <div wicket:id="footer"></div> </div> </body> </html>
  143. 143. Markup inheritance <wicket:extend> <div wicket:id="menu"></div> <div id="main"> <wicket:child /> </div> </wicket:extend>
  144. 144. Markup inheritance <wicket:extend> <div wicket:id="menu"></div> <div id="main"> <wicket:child /> </div> </wicket:extend>
  145. 145. Markup inheritance <wicket:extend> <table> <tr> <td wicket:id="name"></td> <........> </tr> </table </wicket:extend>
  146. 146. Markup inheritance • Inherit markup from child pages • Includes <wicket:head> sections • Works for Panels too • Very easy to create consistent layout
  147. 147. Preparing for the real world Part III
  148. 148. Integrate with Spring & Guice
  149. 149. Getting at Spring public class CheesesPage extends WebPage { private CheesesDao dao; public CheesesPage() { List<Cheese> = dao.getCheeses(); ... } }
  150. 150. Getting at Spring public class CheesesPage extends WebPage { @SpringBean private CheesesDao dao; public CheesesPage() { List<Cheese> = dao.getCheeses(); ... } }
  151. 151. Make Application Spring aware protected void init() { addComponentInstantiationListener( new SpringComponentInjector(this)); }
  152. 152. Make Wicket Guice aware protected void init() { addComponentInstantiationListener( new GuiceComponentInjector(this, getModule())); } private Module getModule() { return new Module() { public void configure(Binder binder) { binder.bind(CheesesDao.class) .to(CheesesDaoImpl.class); }};
  153. 153. Getting at Guice public class CheesesPage extends WebPage { private CheesesDao dao; public CheesesPage() { List<Cheese> = dao.getCheeses(); ... } }
  154. 154. Getting at Guice public class CheesesPage extends WebPage { @Inject private CheesesDao dao; public CheesesPage() { List<Cheese> = dao.getCheeses(); ... } }
  155. 155. Putting your application into production
  156. 156. Test your Wicket application
  157. 157. 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
  158. 158. HelloWorld test @Test public void labelContainsHelloWorld() { }
  159. 159. HelloWorld test @Test public void labelContainsHelloWorld() { WicketTester tester = new WicketTester(); }
  160. 160. HelloWorld test @Test public void labelContainsHelloWorld() { WicketTester tester = new WicketTester(); tester.startPage(HelloWorld.class); }
  161. 161. HelloWorld test @Test public void labelContainsHelloWorld() { WicketTester tester = new WicketTester(); tester.startPage(HelloWorld.class); tester.assertLabel("message", "Hello, World!"); }
  162. 162. Link test @Test public void countingLinkClickTest() { }
  163. 163. Link test @Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); }
  164. 164. Link test @Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); tester.startPage(LinkCounter.class); }
  165. 165. Link test @Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); tester.startPage(LinkCounter.class); tester.assertModelValue("label", 0); }
  166. 166. Link test @Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); tester.startPage(LinkCounter.class); tester.assertModelValue("label", 0); tester.clickLink("link"); }
  167. 167. Link test @Test public void countingLinkClickTest() { WicketTester tester = new WicketTester(); tester.startPage(LinkCounter.class); tester.assertModelValue("label", 0); tester.clickLink("link"); tester.assertModelValue("label", 1); }
  168. 168. Navigation test @Test public void navigateToSecondPage() { WicketTester tester = new WicketTester(); tester.startPage(new FirstPage()); tester.clickLink("link"); tester.assertRenderedPage(SecondPage.class); }
  169. 169. Navigation test @Test public void navigateToSecondPage() { WicketTester tester = new WicketTester(); tester.startPage(new FirstPage()); tester.clickLink("link"); tester.assertRenderedPage( SecondPage.class); }
  170. 170. URL Makeover
  171. 171. UGLY url http://cheesr.com/shop?wicket:bookmarkablePage= %3Acom.cheesr.shop.CheeseDetailsPage&cheese=edam
  172. 172. Prettier urls http://cheesr.com/cheeses?cheese=edam http://cheesr.com/cheeses/cheese/edam http://cheesr.com/cheeses/edam
  173. 173. Mount pages for prettiness mount(new IndexedParamUrlCodingStrategy("cheeses", CheeseDetailsPage.class)); http://cheesr.com/cheeses/edam
  174. 174. Configure for production
  175. 175. 2 configuration modes 1. Development maximize developer happiness 2. Deployment maximize end-user happiness
  176. 176. Development mode • exceptional error pages • dynamic markup reloading • no caching • no javascript/css optimizations • discover mistakes early (serialization, missing components, ...) • Wicket debugger visible
  177. 177. Production 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
  178. 178. Default setting INFO - WebApplication - [WicketInActionApplication] Started Wicket version 1.3.0 in development mode ******************************************************************** *** WARNING: Wicket is running in DEVELOPMENT mode. *** *** ^^^^^^^^^^^ *** *** Do NOT deploy to your live server(s) without changing this. *** *** See Application#getConfigurationType() for more information. *** ********************************************************************
  179. 179. Go to production • System property: java -Dwicket.configuration=deployment • Servlet/filter initialization parameter (web.xml) • Context initialization parameter (web.xml) <init-param> <param-name>configuration</param-name> <param-value>deployment</param-value> </init-param>
  180. 180. The future of Wicket Part IV
  181. 181. • Java 5 all the way CustomerLink(String id, IModel model) Wicket 1.4
  182. 182. • Java 5 all the way CustomerLink(String id, IModel<Customer>) Wicket 1.4
  183. 183. • Java 5 all the way CustomerLink(String id, IModel<Customer>) • Mostly code compatible with Wicket 1.3 Wicket 1.4
  184. 184. • Java 5 all the way CustomerLink(String id, IModel<Customer>) • Mostly code compatible with Wicket 1.3 • Improved OSGi awareness Wicket 1.4
  185. 185. Wicket 1.5 • New Ajax implementation • Improved unit test support • Simplified resources • Improved multi-window support • and much more...
  186. 186. More information • http://wicket.apache.org • blog: http://wicketinaction.com • irc: ##wicket @ irc.freenode.net • User list: users@wicket.apache.org
  187. 187. One more thing...
  188. 188. Wicket in Action • Martijn Dashorst and Eelco Hillenius • August, 2008 | 392 pages • ISBN: 1932394982 • $44.99 Softbound print book - (includes free ebook) • $27.50 PDF ebook
  189. 189. Questions? Ask! the first 6 persons asking a question will receive a free E-Book of Wicket in Action
  190. 190. Thank you for your attention...

×