Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008
-
Upload
baruch-sadogursky -
Category
Technology
-
view
4.653 -
download
0
description
Transcript of Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
2
Apache Wicket – keep it simple!
Baruch Sadogursky
Consultant & Architect, AlphaCSP
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Agenda
• Introduction
• Framework features
• Summary
3
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
4
Introduction
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
5
Intro::Wicket
• “Wicket” means “gate”
• Cricket
• Small door inside a big gate
• Wicket W. Warrick
• Star Wars character
• Why “Wicket”?
• Unique, memorable, easy and not taken
• “Wik-it”
• Lightweight wicket in immovable J2EE gate
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Intro::Apache Wicket
• Component–oriented
• Open Source
• Write HTML (HTML style)
• Write Java (Swing style)
• Tie them together through IDs
6
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
1 <html>
2 <body>
3 <h1 wicket:id="message">Hello, World!</h1>
4 </body>
5 </html>
1 <html>
2 <body>
3 <h1 wicket:id="message">Hello, World!</h1>
4 </body>
5 </html>
1 public class HelloWorld extends WebPage {
2 public HelloWorld() {
3 add(new Label("message", "Hello, World!"));
4 }
5 }
Intro::Hello, World!
7
+
=
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Intro::Looks Familiar?
Wicket:
Swing:
8
1 public class HelloWorld extends JFrame {
2 public HelloWorld() {
3 add(new Label("Hello, World!"));
4 }
5 }
1 public class HelloWorld extends WebPage {
2 public HelloWorld() {
3 add(new Label("message", "Hello, World!"));
4 }
5 }
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Intro::History
9
Mar-04 Jun-08
Apr-04 Jul-04 Oct-04 Jan-05 Apr-05 Jul-05 Oct-05 Jan-06 Apr-06 Jul-06 Oct-06 Jan-07 Apr-07 Jul-07 Oct-07 Jan-08 Apr-08
Mar-04
Jonathan Locke envisioned and originated Wicket
May-05
JavaOne presentation
Jun-05
Wicket 1.0 final
Mar-06
Wicket 1.2 released
Jul-07
Apache Wicket
Jan-08
Wicket 1.3 released
Jun-08
Wicket 1.4 m2
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Intro::Wicket Hype
10
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Intro::Concepts – Component
• Building block of the application
• Renders itself
• Receives events
• More than 220 components in Wicket core & Wicket extensions
• Easily extendable (customizable)
11
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
awt.Component
awt.Container
JContainer
JComponent
JPanel JLabel JButton
awt.Window
awt.Frame
JFrame
Intro:: Concepts – Components
12
Swing Wicket
Component
Label
WebComponent MarkupContainer
Page WebMarkupContainer
WebPage Panel Link
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
1 private IColumn[] getTableColumns() {
2 List<IColumn> columns = new ArrayList<IColumn>();
3 columns.add(new PropertyColumn(new ResourceModel("name"), "name", "name"));
4 columns.add(new PropertyColumn(new ResourceModel("department.name"), "department.name"));
5 columns.add(new TextFieldColumn(new ResourceModel("email"), "email"));
6 return columns.toArray(new IColumn[columns.size()]);
7 }
1 public LoginForm(MarkupContainer parent) {
2 super("loginForm", new CompoundPropertyModel(new User()));
3 parent.add(this);
4 add(new TextField("username").setRequired(true));
5 PasswordTextField passwordTextField = new PasswordTextField("password");
6 passwordTextField.setRequired(true);
7 add(passwordTextField);
8 …
9 }
Intro::Concepts – Model
• No property binding in Java (for now)• Wraps Object, which component renders
• Basic models for single object• Property models for properties
• EL like expressions
• Exactly as Swing Models
13
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Intro::Concepts – Behavior
• Plugin to the component
• Gets component lifecycle events and can react by changing the generated HTML
• Example• SimpleAttributeModifier changes
HTML tag attributes on render
14
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Intro::Concepts
• Application• Configure and init
• Example later
• Session• Strongly typed HTTP session wrapper
• RequestCycle• Represents the processing of a request
• Tells RequestCycleProcessor what to do• How to handle events
• How to generate response
15
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
16
Wicket Features Review
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
1 protected void init() {
2 super.init();
3 addComponentInstantiationListener(new SpringComponentInjector(this));
4 getResourceSettings().setThrowExceptionOnMissingResource(true);
5 mountBookmarkablePage("hello_world.html", HelloWorld.class);
6 }
7
8 @Override
9 public Class getHomePage() {
10 return SearchPage.class;
11 }
Features::Configuration
• No Wicket XML files• Convention over configuration• Configuration done in Java• Spring integration
• Just enable injecting interceptor
17
1 @SpringBean
2 private UserService userService;
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::View Technology
• Valid XHTML
• No custom markup (almost)• wicket:id attribute
• The only mandatory one
• <wicket:message/> resource bundle
lookup
• See I18N
18
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::View Technology
• Reuse HTML as it was Java• <wicket:child/>
• <wicket:extend/>
• <wicket:panel/>
19
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <?xml version="1.0" encoding="UTF-8"?>
4 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/">
5 <head>
6 …
11 </head>
12 <body>
13 <wicket:child/>
14 </body>
15 </html>
1 <wicket:extend>
2 <div align="right" class="header" wicket:id="welcomePanel"></div>
3 <div class="phoneBook" align="center" wicket:id="searchPanel"></div>
4 <div class="phoneBook" align="center" wicket:id="resultsPanel"></div>
5 </wicket:extend>
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
1 <wicket:panel>
2 <table>
3 <tr>
4 <td class="header"><wicket:message key="user"/>: <span wicket:id="username"></span></td>
5 <td class="headerSeperator">|</td>
6 <td class="header"><a href="#" wicket:id="logout"><wicket:message key="logout"/></a></td>
7 </tr>
8 </table>
9 </wicket:panel>
Features::View Technology
• Reuse HTML as it was Java• <wicket:child/>
• <wicket:extend/>
• <wicket:panel/>
20
1 <wicket:extend>
2 <div align="right" class="header" wicket:id="welcomePanel"></div>
3 <div class="phoneBook" align="center" wicket:id="searchPanel"></div>
4 <div class="phoneBook" align="center" wicket:id="resultsPanel"></div>
5 </wicket:extend>
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::Page Flow
• Inside onSubmit (buttons, links and forms)• setResponsePage(SomePage.class);
• setResponsePage(somePage);
21
1 @Override
2 protected void onSubmit() {
3 User credentials = (User) this.getModelObject();
4 WicketSession session = WicketSession.get();
5 User loggedInUser = userService.login(credentials);
6 if (loggedInUser != null) {
7 session.setUser(loggedInUser);
8 setResponsePage(SearchPage.class);
9 } else {
10 this.error("Sorry, …");
11 setModelObject(new User());
12 }
13 }
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::Form Binding
• Form is a component
• So, it is backed up with model
22
1 private SearchForm(MarkupContainer parent) {
2 super("searchForm", new CompoundPropertyModel(new Contact()));
3 parent.add(this);
4 add(new TextField("name"));
5 TextField emailTextField = new TextField("email");
6 emailTextField.add(EmailAddressValidator.getInstance());
7 add(emailTextField);
8 …
9 }
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::Table Sorting
• Headers should be added to table
• Property expression is optionally passed when constructing Column
• If passed – the header will be clickable
23
1 private static class SortablePagedDataTable extends DataTable {
2 private SortablePagedDataTable(String id, IColumn[] tableColumns,
3 ContactsListDataProvider contacts, int rowsPerPage) {
4 super(id, tableColumns, contacts, rowsPerPage);
5 addTopToolbar(new AjaxFallbackHeadersToolbar(this, contacts));
6 addBottomToolbar(new AjaxNavigationToolbar(this));
7 }
8 }
1 private IColumn[] getTableColumns() {
2 List<IColumn> columns = new ArrayList<IColumn>();
3 columns.add(new PropertyColumn(new ResourceModel("name"), "name", "name"));
4 columns.add(new PropertyColumn(new ResourceModel("department.name"), "department.name"));
5 columns.add(new TextFieldColumn(new ResourceModel("email"), "email"));
6 return columns.toArray(new IColumn[columns.size()]);
7 }
8
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::Table Sorting
• You generate the displayed data
• So, you are in charge of actual sorting
• Property expression and sort direction is provided
24
1 public class ContactsListDataProvider extends SortableDataProvider {
2 …
3 public Iterator<Contact> iterator(int first, int count) {
4 List<Contact> sublist = data.subList(first, first + count);
5 SortParam sort = getSort();
6 if (sort != null && "name".equals(sort.getProperty())) {
7 Collections.sort(sublist);
8 if (!sort.isAscending()) {
9 Collections.reverse(sublist);
10 }
11 }
12 return sublist.iterator();
13 }
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::Pagination
• Navigation toolbar should be added to table (top or bottom)
• Rows per page count is passed in the constructor
25
1 private static class SortablePagedDataTable extends DataTable {
2 private SortablePagedDataTable(String id, IColumn[] tableColumns,
3 ContactsListDataProvider contacts, int rowsPerPage) {
4 super(id, tableColumns, contacts, rowsPerPage);
5 addTopToolbar(new AjaxFallbackHeadersToolbar(this, contacts));
6 addBottomToolbar(new AjaxNavigationToolbar(this));
7 }
8 }
1 public ResultsPanel(ContactsListDataProvider contactsDataProvider) {
2 super("resultsPanel");
3 DataTable contactsTable = new SortablePagedDataTable("contactsTable",
4 getTableColumns(), contactsDataProvider, 10);
5 add(contactsTable);
6 }
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::Pagination
• You generate the displayed data
• So, you are in charge of actual sublisting
• First and count are provided
26
1 public class ContactsListDataProvider extends SortableDataProvider {
2 …
3 public Iterator<Contact> iterator(int first, int count) {
4 List<Contact> sublist = data.subList(first, first + count);
5 SortParam sort = getSort();
6 if (sort != null && "name".equals(sort.getProperty())) {
7 Collections.sort(sublist);
8 if (!sort.isAscending()) {
9 Collections.reverse(sublist);
10 }
11 }
12 return sublist.iterator();
13 }
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
• “Required” validation – just say
• Validation errors added to their own <div> (css it at will)
27
Features::Validations (Server)
1 public LoginForm(MarkupContainer parent) {
2 super("loginForm", new CompoundPropertyModel(new User()));
3 parent.add(this);
4 add(new TextField("username").setRequired(true));
5 PasswordTextField passwordTextField = new PasswordTextField("password");
6 passwordTextField.setRequired(true);
7 add(passwordTextField);
8 FeedbackPanel feedbackPanel = new FeedbackPanel("feedback");
9 feedbackPanel.setEscapeModelStrings(false);
10 add(feedbackPanel);
11 }
1 <tr>
2 <td colspan="2" class="feedback" wicket:id="feedback"/>
3 </tr>
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
• Other validations – add Validators to the components
• 24 ready validators in wicket-core and wicket-extensions
28
Features::Validations (Server)
1 private SearchForm(MarkupContainer parent) {
2 super("searchForm", new CompoundPropertyModel(new Contact()));
3 parent.add(this);
4 add(new TextField("name"));
5 TextField emailTextField = new TextField("email");
6 emailTextField.add(EmailAddressValidator.getInstance());
7 …
12 }
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::Validations (Client)
• Server validations are must
• Target of client validation – provide earlier feedback to the user
• Client validations should be copy of Java code in JS
• No automatic JS port for server-side validations (only Google can?)
29
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::Validations (Client)
• Solution – call server-side validations in AJAX
• Same experience for the user
• Slower on slow connections
30
1 private SearchForm(MarkupContainer parent) {
2 super("searchForm", new CompoundPropertyModel(new Contact()));
3 parent.add(this);
4 add(new TextField("name"));
5 TextField emailTextField = new TextField("email");
6 emailTextField.add(EmailAddressValidator.getInstance());
7 …
8 AjaxFormValidatingBehavior.addToAllFormComponents(this, "onblur");
9 }
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::AJAX
• Use AJAX components instead of non-AJAX ones
• Add components to be refreshed
31
1 private SearchForm(MarkupContainer parent) {
2 super("searchForm", new CompoundPropertyModel(new Contact()));
3 parent.add(this);
4 …
12 add(new AjaxButton("submit", this){
13
14 @Override
15 protected void onSubmit(AjaxRequestTarget target, Form form) {
16 Contact exampleContact = (Contact) SearchForm.this.getModelObject();
17 List<Contact> contacts = companyService.findContactsByExample(exampleContact);
18 contactsDataProvider.setData(contacts);
19 ResultsPanel resultsPanel = ((SearchPage) getPage()).getResultsPanel();
20 target.addComponent(resultsPanel);
21 }
22 });
23 AjaxFormValidatingBehavior.addToAllFormComponents(this, "onblur");
24 }
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::AJAX
32
• JS is generated using Dojo and Script.aculo.us
• Automatic fallback to non-jscomponents
1 <script type="text/javascript"
2 src="resources/org.apache.wicket.markup.html.WicketEventReference/wicket-event.js">
3 </script>
4 <script type="text/javascript"
5 src="resources/org.apache.wicket.ajax.WicketAjaxReference/wicket-ajax.js">
6 </script>
7 <script type="text/javascript"
8 src="resources/org.apache.wicket.ajax.AbstractDefaultAjaxBehavior/wicket-ajax-debug.js">
9 </script>
10 <script type="text/javascript"
11 id="wicket-ajax-debug-enable"><!--/*--><![CDATA[/*><!--*/
12 wicketAjaxDebugEnable = true;
13 /*-->]]>*/</script>
14 <script type="text/javascript"
15 src="resources/org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteBehavior/wicket-autocomplete.js">
16 </script>
17 <script type="text/javascript"><!--/*--><![CDATA[/*><!--*/
18 Wicket.Event.add(window, "domready", function() {
19 new Wicket.AutoComplete('department2',
20 '?wicket:interface=:2:searchPanel:searchForm:department::IActivePageBehaviorListener:1:&wicket:ignoreIfNotActive=true',
21 false);
22 });
23 /*-->]]>*/</script>
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::AJAX
33
• Great debug utility
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::Error Handling – Dev
• Very self-explanatory error pages
34
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::Error Handling – Prod
35
• Application level config of different kinds of errors
1 private void initExceptionHandeling() {
2 IApplicationSettings appSettings = getApplicationSettings();
3 appSettings.setPageExpiredErrorPage(PageExpiredErrorPage.class);
4 appSettings.setAccessDeniedPage(AccessDeniedPage.class);
5 appSettings.setInternalErrorPage(InternalErrorPage.class);
6 getExceptionSettings().setUnexpectedExceptionDisplay(SHOW_INTERNAL_ERROR_PAGE);
7 }
• Per page configuration 1 @Override
2 protected void onSubmit(AjaxRequestTarget target, Form form) {
3 Contact exampleContact = (Contact) SearchForm.this.getModelObject();
4 try {
5 List<Contact> contacts = companyService.findContactsByExample(exampleContact);
6 contactsDataProvider.setData(contacts);
7 ResultsPanel resultsPanel = ((SearchPage) getPage()).getResultsPanel();
8 target.addComponent(resultsPanel);
9 } catch (RuntimeException e) {
10 getRequestCycle().onRuntimeException(new SearchErrorPage(e), e);
11 }
12 }
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::Error Handling – Prod
• onRuntimeException override in RequestCycle
• In this case you get the actual exception object
36
1 @Override
2 public RequestCycle newRequestCycle(Request request, Response response) {
3 return new WebRequestCycle(this, (WebRequest) request, response) {
4
5 @Override
6 public Page onRuntimeException(Page page, RuntimeException e) {
7 return new InternalErrorPage(e);
8 }
9 };
10 }
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::I18N Support
• Full I18N of all the application using Resource bundles• Use <wicket:message key=“…"/>
instead of hard-coded text
37
1 <tr>
2 <td valign=middle align=right width=25%><b><wicket:message key="username"/></b></td>
3 <td valign=middle>
4 <input class="loginField" type="text" id="username" size="25" tabindex=1
5 accessKey="u" wicket:id="username">
6 </td>
7 </tr>
1 page.title=Login
2 username=<u>U</u>sername
3 password=<u>P</u>assword
4 submit=Login
1 page.title=
2 username=
3 password=
4 submit=
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features::L10N Support
• Use “HTML Bundles”• Similar to resource bundles, but for HTML pages
• LoginPage.html – default• LoginPage_iw.html – right-to-left
38
1 <table class="loginTable" border="1" style="direction: rtl;">
2 <tr>
3 …
4 </tr>
5 </table>
1 public WicketSession(Request request) {
2 super(request);
3 setLocale(new Locale("iw"));
4 }
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Features:: Documentation
• Source
• API documentation
• Nabble• Forum & Mailing List
• Books• Pro Wicket
• Wicket in Action• Early Access available, in print next month
• Sites (see References)
39
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
40
Summary
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Summary
Feature Summary
Configuration No XML!
View technology Valid XHTML Cut to pieces
Page flow No XML!
Form binding Swing-like models
Table sorting Eeeeasy
Pagination Eeeeasy
Validations No JS generation
AJAX Eeeeasy, but JS can be better
Error handling Powerful and configurable
I18n support Java resource bundles
Documentation Tons, can be organized better
41
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Summary::Java!
• Fast learning curve
• MVC at component level
• Truly object oriented
• Code centric
• Trivial component creation
• Java FWs integration
• Full debuggability
42
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Summary::Cons
• Internals are complex
• The API is too big
• No structured “Best Practices”
• Documentation is a mess
• Java limitations
• Anonymous classes instead of closures
• Generics troubles
43
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Summary::Cons
• A lot of Java code required
• Maintainability
• No generics support in API (until 1.4)
• No automatic client-side validation generation
• Not suitable for very dynamic pages
• HTML cut between different files
• Not so comfortable for HTML coders
44
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Summary::The Future
• Wicket 1.4• Generics
• Model<T>• Component<T>
• M2 is available
• Wicket 1.5• Multiple extend/child areas• Proxy Model
• Strongly typed properties
• Tabbed browsers support• Many more
45
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
Summary:: References
• wicket.apache.org
• cwiki.apache.org/WICKET
• wicketstuff.org
• www.wicket-library.com
• issues.apache.org/jira/browse/WICKET
46
Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
47
Thank
You!