Wicket Explained Ease your way into Ease your way into Component - - PowerPoint PPT Presentation
Wicket Explained Ease your way into Ease your way into Component - - PowerPoint PPT Presentation
Wicket Explained Ease your way into Ease your way into Component Based Web Application Component Based Web Application Development Development Goals Explain why CBD is a good fit for the web tier Show the basics of a Wicket
Goals
- Explain why CBD is a good fit for the web
tier
- Show the basics of a Wicket application:
pages, components and models
- See how web application development
doesn’t have to be difficult
Agenda
- Introduction
- Java web frameworks
- Applications, pages, components & models
- 10 minute workout
- Processing Input
- Summary & Questions
What is Wicket?
- Open Source (Apache 2 license)
- Started in 2004 by Jonathan Locke
- Component Oriented
- Clean separation of Markup and Code
- If you know Java and HTML, then you
already know a lot about Wicket
- Programmer freedom
Agenda
- Introduction
- Java web frameworks
- Applications, pages, components & models
- 10 minute workout
- Processing Input
- Summary & Questions
Java web frameworks
- CGI/ Servlets;
- Servlets combined with templating
– Webmacro, Velocity
- JSP (‘model 1’ – usebean)
- ‘Model 2’ a.k.a. ‘Web MVC’
– Struts, WebWork, SpringMVC, Maverick, etc. – Request oriented
- Component based
Keeping state?
- Wicket has stateful components
- REST (Representational State Transfer) vs
Stateful programming
– Stateless service layers: are we back to procedural programming once again? – Cost of development hours – Processor & bandwidth vs memory – Do your pages really just do one thing?
- Keeping state gets you:
– Self contained components – Easy and elegant programming
Wicket's Goals
- Bring OO back to the web tier
– Let developers focus on structure instead of
- peration
- Make reuse (using and providing) easy
- Separate concerns
– HTML for presentation
- Minimal or no scripting
– Java for state and Model/ Control
- Strongly typed
- Use your Java IDE
- Easy = productive and maintainable
Agenda
- Introduction
- Java web frameworks
- Applications, pages, components & models
- 10 minute workout
- Processing Input
- Summary & Questions
Applications
- Application defines:
– Pages:
- home page
- error/stale page
– Settings
- development mode
- deployment mode
– Request Cycle strategy – Factories for:
- resources
- sessions
- converters
Pages
- Pages group your components
- Pages can inherit from other pages
– The markup as well -> template base page!
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1>
Pages
- Markup and Java can be next to each other
– Default: in same directory on classpath
- allows packaging of components (jar drop-ins)
- easy access while developing
page class page markup
Components
- Everything is a component in Wicket
– A component has a wicket:id – A component has markup associated – A component is a Java class
- in markup: wicket:id
- in Java: Component.id
<span wicket:id=“foo”> </span> new Label(“foo”, “bar”); Markup Java
Components
- Everything is a component in Wicket
– A component has a wicket:id – A component has markup associated
- Components can be nested
row
col col col col col
row
col col col col col
listview ‘col’
Components
- Everything is a component in Wicket
– A component has a wicket:id – A component has markup associated
- Components can be nested
row
col col col col col
row
col col col col col
listview ‘row’
Components
- Wicket supports all basic HTML tags
– <a href> – <input type=“XXX”> – <form> – <img>, <map> – <frame>
- Components support JavaScript, CSS
– contribute to header – local
Components
- Components are reusable
– address input form, – search panel, – paging navigator for listview, – date picker
Components
- Components are reusable
– address input form, – search panel, – paging navigator for listview, – date picker
- Components are JAR-able
– package Java, HTML, CSS, images, JavaScript – put JAR in classpath – use component in your application
Component Examples (1/3)
Simple Simple label component label component
HTML markup: <span wicket:id=“message”>contents go here</span> Java code: new Label(“message”, “Hello, World!”);
Component Examples (2/3)
Simple Simple input input field component field component
HTML markup: <input wicket:id=“name” type=“text” value=“xxxx” /> Java code: new TextField(“name”)
Component Examples (3/3)
Form with nested field Form with nested field
HTML markup: <form wicket:id=“customerForm”> <input wicket:id=“zipCode” type=“text” value=“xxxx” /> </form> Java code: Form form = new Form(“customerForm”, customer); form.add(new TextField(“zipcode”, new PropertyModel(customer, “zipCode”));
Models
- Models bind your POJO’s to Wicket
components
- Models are the ‘brains’ of your app
Label() <<Person>> + name : String + city : String <<Model>> wicket POJO’s
Models
- Basic models:
– Model – PropertyModel – AbstractDetachableModel
- ‘Advanced’ models:
– LoadableDetachableModel – CompoundPropertyModel – BoundCompoundPropertyModel – StringResourceModel
Model examples
Simple model: Simple model:
add(new Label("message", "Hello World!"));
Model examples
Binding to POJO: Binding to POJO:
add(new Label(“name”, new PropertyModel(person, “name”))); <span wicket:id=“name”>will be replaced</span>
Model examples
Using ID’s to bind components to properties: Using ID’s to bind components to properties:
form = new Form(“person”, new CompoundPropertyModel(person)); form.add(new TextField(“name”)); form.add(new TextField(“city”));
Agenda
- Introduction
- Java web frameworks
- Applications, pages, components & models
- 10 minute workout
- Processing Input
- Summary & questions
10 minute workout
10 minute workout
Mocking Markup
Page <table> link (<a href>) <h1>
Mocking Markup
Page <table> rows (<tr>) link (<a href>) <h1>
Mocking Markup
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1>
Mocking Markup
<html> ... <body> <h1>Addresses</h1> <table> <!-- heading --> <tr> <td><span>John Doe</span></td> <td><span>555-5555</span></td> <td><span>friend</span></td> </tr> </table> </body> </html>
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1>
Mocking Markup
<html> ... <body> <h1>Addresses</h1> <table> <!-- heading --> <tr wicket:id=“rows”> <td><span>John Doe</span></td> <td><span>555-5555</span></td> <td><span>friend</span></td> </tr> </table> </body> </html>
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1>
Mocking Markup
<html> ... <body> <h1>Addresses</h1> <table> <!-- heading --> <tr wicket:id=“rows”> <td><span wicket:id=“name”>John Doe</span></td> <td><span wicket:id=“telnr”>555-5555</span></td> <td><span wicket:id=“type”>friend</span></td> </tr> </table> </body> </html>
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1>
From Markup to Java
public class public class AddressPage extends extends WebPage { public public AddressPage() { } }
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1>
From Markup to Java
public class public class AddressPage extends extends WebPage public public AddressPage() { add(new new AddressListView(“rows”, addresses)); } public class public class AddressListView extends extends ListView { public public AddressListView(String name, IModel model) { super super(name, model); } } }
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1>
From Markup to Java
public class public class AddressPage extends extends WebPage public public AddressPage() { add(new new AddressListView(“rows”, addresses)); } public class public class AddressListView extends extends ListView { public public AddressListView(String name, IModel model) { super super(name, model); } protected void populateItem(ListItem item) { item.add(new Label(“name”)); item.add(new Label(“telnr”)); item.add(new Label(“type”)); } } }
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1>
Application
public class AddressApplication extends WebApplication { public AddressApplication() { super(); getPages().setHomePage(AddressPage.class); } }
But where’s the XML?
- No extra XML configuration necessary
- Just web.xml
<web-app> <display-name>Wicket Addressbook</display-name> <servlet> <servlet-name>address</servlet-name> <servlet-class>wicket.protocol.http.WicketServlet</servlet-class> <init-param> <param-name>applicationClassName</param-name> <param-value>wicket.examples.AddressApplication</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>address</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping> </web-app>
Summary
- Create markup
- Identify components
- Assign wicket:id’s to components
- Create Java class (extends WebPage)
- Add components to Page
- Define Application
- Add wicket servlet to
web.xml
10 minute workout
Adding behaviour
- Add delete link to each item
Page <table> rows (<tr>)
name telnr f/f
link (<a href>) <h1> delete
Mocking Markup
... <tr> <td><span wicket:id=“name”>John Doe</span></td> <td><span wicket:id=“telnr”>555-555</span></td> <td><span wicket:id=“type”>friend</span></td> <td><a href=“#”>delete</a></td> </tr>
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1> del
Add Wicket ID
... <tr> <td><span wicket:id=“name”>John Doe</span></td> <td><span wicket:id=“telnr”>555-555</span></td> <td><span wicket:id=“type”>friend</span></td> <td><a wicket:id=“delete” href=“#”>delete</a></td> </tr>
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1> del
Add Link component
protected void populateItem(ListItem item) { item.add(new Label(“name”)); item.add(new Label(“telnr”)); item.add(new Label(“type”)); item.add(new Link(“delete”)); }
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1> del
<a wicket:id=“delete” href=“#”>delete</a>
Add onClick()
protected void populateItem(ListItem item) { item.add(new Label(“name”)); item.add(new Label(“telnr”)); item.add(new Label(“type”)); item.add(new Link(“delete”) { public void onClick() { Object addr = getParent().getModelObject(); AddressDAO.delete((Address)addr); } } }
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1> del
Summary
- Added link to markup
- Added wicket:id to link tag
- Added link component to listitem
- Added onClick() behaviour to link
10 minute workout
Adding paging to the list
- Add paging to the list
Page
<table> rows (<tr>) name telnr f/f link (<a href>) <h1> del
Adding paging to the list
- Add paging to the list
Page
<table> rows (<tr>) name telnr f/f link (<a href>) <h1> del
navigator
Mocking Markup
... <td><span wicket:id=“telnr”>555-555</span></td> <td><span wicket:id=“type”>friend</span></td> <td><a wicket:id=“delete” href=“#”>delete</a></td> </tr> <tr> <td colspan=“4”> <span>NAVIGATOR</span> </td> </tr> </table>
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1> del
navigator
Assign Wicket ID
... <td><span wicket:id=“telnr”>555-555</span></td> <td><span wicket:id=“type”>friend</span></td> <td><a href=“#”>delete</a></td> </tr> <tr> <td colspan=“4”> <span wicket:id=“navigator”>NAVIGATOR</span> </td> </tr> </table>
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1> del
navigator
Make ListView pageable
public class AddressPage extends WebPage { public AddressPage() { add(new AddressListView(“rows”, addresses)); } public class AddressListView extends PageableListView PageableListView { public AddressListView(String name, IModel model) { super(name, model, 2 , 2); } } }
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1> del
navigator
number of items per page
Add Navigator component
public class AddressPage extends WebPage { public AddressPage() { PageableListView lv = new AddressListView(“rows”,addresses); add(lv); add(new PagingNavigator(“navigator”, lv)); } ... }
Page <table> rows (<tr>) name telnr f/f link (<a href>) <h1> del
navigator
Summary
- Add navigator to markup
- Add wicket:id to navigator tag (span)
- Change ListView into PageableListView
- Add Navigator component to Page
- That’s it!
10 minute workout
- Created ‘complex’ page
- ~ 10 minutes!
- Just Java and HTML
- No weird stuff in HTML
- No weird XML configurations
Agenda
- Introduction
- Java web frameworks
- Applications, pages, components & models
- 10 minute workout
- Processing Input
– Forms – Validation
- Summary & Questions
fieldset
Processing Input
h1 form input input input select submit Name: Area code: Phone num: Friend or :
fieldset
Processing Input
h1 form input input input select submit Name: Area code: Phone num: Friend or :
fieldset
Processing Input
h1 form input input input select submit Name: Area code: Phone num: Friend or :
... <body><h1>Add New Address</h1> <fieldset><legend>Person Data</legend> <form> ... <th>Name:</th> <td><input type=“text” /></td> ... <th>Area code:</th> <td><input type=“text” /></td> ... <td><input type=“submit” /></td> ... </form>
Mocking Markup
fieldset h1 form input input input select submit Name: Area: Phone: Friend or :
... <body><h1>Add New Address</h1> <fieldset><legend>Person Data</legend> <form wicket:id=“form”> ... <th>Name:</th> <td><input type=“text” /></td> ... <th>Area code:</th> <td><input type=“text” /></td> ... <td><input type=“submit” /></td> ... </form>
fieldset h1 form input input input select submit Name: Area: Phone: Friend or :
Assign Wicket ID
... <body><h1>Add New Address</h1> <fieldset><legend>Person Data</legend> <form wicket:id=“form”> ... <th>Name:</th> <td><input wicket:id=“name” type=“text” /></td> ... <th>Area code:</th> <td><input wicket:id=“areacode” type=“text” /></td> ... <td><input type=“submit” /></td> ... </form>
fieldset h1 form input input input select submit Name: Area: Phone: Friend or :
Assign Wicket ID
From Markup to Java
public class AddPersonPage extends WebPage { public AddPersonPage() { } }
fieldset h1 form input input input select submit Name: Area: Phone: Friend or :
From Markup to Java
public class AddPersonPage extends WebPage { public AddPersonPage() { add(new EditPersonForm(“form”, new Person())); } public class EditPersonForm extends Form { public EditPersonForm(String name, Person p) { super(name, new CompoundPropertyModel(p)); } } }
fieldset h1 form input input input select submit Name: Area: Phone: Friend or :
From Markup to Java
public class AddPersonPage extends WebPage { public AddPersonPage() { add(new EditPersonForm(“form”, new Person())); } public class EditPersonForm extends Form { public EditPersonForm(String name, Person p) { super(name, new CompoundPropertyModel(p)); add(new TextField(“name”)); add(new TextField(“areacode”)); ... } } }
fieldset h1 form input input input select submit Name: Area: Phone: Friend or :
From Markup to Java
public class AddPersonPage extends WebPage { public AddPersonPage() { add(new EditPersonForm(“form”, new Person())); } public class EditPersonForm extends Form { public EditPersonForm(String name, Person p) { ... } protected void onSubmit() { Person p = (Person)getModelObject(); PersonDAO.save(p); } } }
fieldset h1 form input input input select submit Name: Area: Phone: Friend or :
Summary
- Created HTML mockup
- Assigned Wicket ID’s
- Created Java page
- Created Form class
- Added fields to form
- Implemented onSubmit
- Done
Validation
- Many default validators available
– Type (Date, Integer, etc) – RequiredValidator
- Localization
– Localized parsing of values – Localized messages using resource bundles
- How does it work?
– Automatic validation on form submit – Beans get populated on valid submission – Form.onSubmit is called after population
fieldset
Adding Feedback
h1 form input input input select submit Name: Area code: Phone num: Friend or :
fieldset
Adding Feedback
h1 form
input input input select submit Name: Area code: Phone num: Friend or :
feedback
Adding Feedback
... <body><h1>Add New Address</h1> <span wicket:id=“feedback”></span> <fieldset><legend>Person Data</legend> <form> ... <th>Name:</th> <td><input type=“text” /></td> ... <th>Area code:</th> <td><input type=“text” /></td> ... <td><input type=“submit” /></td> ... </form>
fieldset h1 form input input input select submit Name: Area: Phone: Friend or : feedback
Adding Feedback
public class AddPersonPage extends WebPage { public AddPersonPage() { add(new EditPersonForm(“form”, new Person())); } public class EditPersonForm extends Form { public EditPersonForm(String name, Person p) { super(name, p); ... } } }
fieldset h1 form input input input select submit Name: Area: Phone: Friend or : feedback
Adding Feedback
public class AddPersonPage extends WebPage { public AddPersonPage() { FeedbackPanel fb = new FeedbackPanel(“feedback”) add(fb); add(new EditPersonForm(“form”, new Person(), fb)); } public class EditPersonForm extends Form { public EditPersonForm(..., IFeedback fb) { super(..., fb); ... } } }
fieldset h1 form input input input select submit Name: Area: Phone: Friend or : feedback
Adding Validation
- Make ‘name’ required
- Make ‘areacode’ between 200 and 999
public class EditPersonForm extends Form { public EditPersonForm(..., IFeedback feedback) { super(..., feedback); add(new TextField(“name”)); add(new TextField(“areacode”)); ...
Adding Validation
- Make ‘name’ required
- Make ‘areacode’ between 200 and 999
public class EditPersonForm extends Form { public EditPersonForm(String name, Person p) { super(name, new CompoundPropertyModel(p)); add(new RequiredTextField(“name”)); add(new TextField(“areacode”)); ...
Adding Validation
- Make ‘name’ required
- Make ‘areacode’ between 200 and 999
public class EditPersonForm extends Form { public EditPersonForm(String name, Person p) { super(name, new CompoundPropertyModel(p)); add(new RequiredTextField(“name”)); add(new TextField(“areacode”)); ...
AddPersonPage.properties:
form.name.RequiredValidator=${name} is required
Adding Validation
- Make ‘name’ required
- Make ‘areacode’ between 200 and 999
public class EditPersonForm extends Form { public EditPersonForm(String name, Person p) { super(name, new CompoundPropertyModel(p)); add(new RequiredTextField(“name”)); add(new TextField(“areacode”)); ...
AddPersonPage.properties:
form.name.RequiredValidator=${name} is required
Adding Validation
- Make ‘name’ required
- Make ‘areacode’ between 200 and 999
public class EditPersonForm extends Form { public EditPersonForm(String name, Person p) { super(name, new CompoundPropertyModel(p)); add(new RequiredTextField(“name”)); add(new TextField(“areacode”).add( IntegerValidator.range(200,999)));
AddPersonPage.properties:
form.name.RequiredValidator=${name} is required
Adding Validation
- Make ‘name’ required
- Make ‘areacode’ between 200 and 999
public class EditPersonForm extends Form { public EditPersonForm(String name, Person p) { super(name, new CompoundPropertyModel(p)); add(new RequiredTextField(“name”)); add(new TextField(“areacode”).add( IntegerValidator.range(200,999)));
AddPersonPage.properties:
form.name.RequiredValidator=${name} is required form.areacode.IntegerValidator=${input} is not between ${min} and ${max}
Adding Validation
- Make ‘name’ required
- Make ‘areacode’ between 200 and 999
public class EditPersonForm extends Form { public EditPersonForm(String name, Person p) { super(name, new CompoundPropertyModel(p)); add(new RequiredTextField(“name”)); add(new TextField(“areacode”));
AddPersonPage.properties:
form.name.RequiredValidator=${name} is required
Summary
- Add feedback to page
- Add validation to fields
- Create page.properties file
- Add validation message to properties file
- Done
Conclusions
- Component based web development is the
future
- Wicket is
– Easy – Smart – Pretty – Fun
- All HTML and Java
- No complicated configuration files
Questions?
Links
- http://wicket.sourceforge.net
- http://wicket-stuff.sourceforge.net
Web MVC
- Current ‘de-facto standard’ pattern
- One front controller, Actions (a.k.a.
Commands) and a template technology
- URL – action mapping
- Each action can reference multiple views
- Actions process input and prepare a View.
Problems with Web MVC (1)
- Bad support for complexity, like
– Pages with independent UI elements – UI elements that span multiple pages
- Commonly ‘solved’ by:
– Command chaining – Filter layering – Uncontrolled, ah-hoc HttpSession usage – Interceptors
Problems with Web MVC (2)
- No reuse.
– Every project has to start from scratch
- No library for e.g. address panels, search/results
panels, etc.
– Even within projects a lot of copy ‘n paste
- Reusing pages or panels for application variant
- Inheriting behavior by extending gets messy
– No 3rd party components
Problems with Web MVC (3)
- Encourages bad programming practices
– Thinking ‘how’ instead of ‘what’
- Operations vs. Components as HLS call it
– Monolithic commands with copy ‘n paste code – Display hacks all over
- Java fragments in JSPs
- Velocity tools and other ‘utility classes’
– Framework layering.
- Filters for opening/ closing Hibernate sessions,
cleaning up session state, etc
- Navigation
- Composition
Problems with Web MVC (4)
- Scales bad for development
– URL - Command/ view mapping
- One or a few large xml files
– Hard to find stuff – Team update conflicts
- Combine Command code, mapping and view code
to understand what is happening
– Did I mention framework layering?
– Fragile to configuration typos – Copy ‘n paste code is a maintenance problem – Lack of reuse gives less team partitioning
- ptions