Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008
Upcoming SlideShare
Loading in...5
×
 

Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008

on

  • 7,623 views

Full source code of the demo application is downloadble from http://www.alphacsp.com/Events/Web-Frameworks-2008/Demos/wicket-demo.zip

Full source code of the demo application is downloadble from http://www.alphacsp.com/Events/Web-Frameworks-2008/Demos/wicket-demo.zip

Statistics

Views

Total Views
7,623
Views on SlideShare
7,607
Embed Views
16

Actions

Likes
3
Downloads
246
Comments
0

3 Embeds 16

http://www.slideshare.net 12
http://www.linkedin.com 3
http://www.slideee.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008 Wicket Presentation @ AlphaCSP Java Web Frameworks Playoff 2008 Presentation Transcript

  • Apache Wicket – keep it simple! Baruch Sadogursky Consultant & Architect, AlphaCSP 2 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Agenda • Introduction • Framework features • Summary 3 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Introduction 4 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • 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 5 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
  • Intro::Hello, World! 1 public class HelloWorld extends WebPage { 2 public HelloWorld() { 3 add(new Label(quot;messagequot;, quot;Hello, World!quot;)); 4 } 5 } + 1 <html> 2 <body> 3 <h1 wicket:id=quot;messagequot;>Hello, World!</h1> 4 </body> 5 </html> = 1 <html> 2 <body> 3 <h1 wicket:id=quot;messagequot;>Hello, World!</h1> 4 </body> 5 </html> 7 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Intro::Looks Familiar? Wicket: 1 public class HelloWorld extends WebPage { 2 public HelloWorld() { 3 add(new Label(quot;messagequot;, quot;Hello, World!quot;)); 4 } 5 } Swing: 1 public class HelloWorld extends JFrame { 2 public HelloWorld() { 3 add(new Label(quot;Hello, World!quot;)); 4 } 5 } 8 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Intro::History Mar-04 Jonathan Locke envisioned and originated Wicket Jun-05 Mar-06 Jul-07 Jan-08 Jun-08 May-05 Wicket 1.0 final Wicket 1.2 released Apache Wicket Wicket 1.3 released Wicket 1.4 m2 JavaOne presentation 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 Jun-08 9 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
  • Intro:: Concepts – Components Swing Wicket awt.Component Component awt.Container WebComponent MarkupContainer awt.Window JContainer Label Page WebMarkupContainer awt.Frame JComponent WebPage Panel Link JFrame JPanel JLabel JButton 12 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • 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 1 private IColumn[] getTableColumns() { 2 List<IColumn> columns = new ArrayList<IColumn>(); 3 columns.add(new PropertyColumn(new ResourceModel(quot;namequot;), quot;namequot;, quot;namequot;)); 4 columns.add(new PropertyColumn(new ResourceModel(quot;department.namequot;), quot;department.namequot;)); 5 columns.add(new TextFieldColumn(new ResourceModel(quot;emailquot;), quot;emailquot;)); 6 return columns.toArray(new IColumn[columns.size()]); 7 } 1 public LoginForm(MarkupContainer parent) { 2 super(quot;loginFormquot;, new CompoundPropertyModel(new User())); 3 parent.add(this); 4 add(new TextField(quot;usernamequot;).setRequired(true)); 5 PasswordTextField passwordTextField = new PasswordTextField(quot;passwordquot;); 6 passwordTextField.setRequired(true); 7 add(passwordTextField); 8 … 9 } 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
  • Wicket Features Review 16 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Features::Configuration • No Wicket XML files • Convention over configuration • Configuration done in Java • Spring integration • Just enable injecting interceptor 1 @SpringBean 1 protected void init() { 2 private UserService userService; 2 super.init(); 3 addComponentInstantiationListener(new SpringComponentInjector(this)); 4 getResourceSettings().setThrowExceptionOnMissingResource(true); 5 mountBookmarkablePage(quot;hello_world.htmlquot;, HelloWorld.class); 6 } 7 8 @Override 9 public Class getHomePage() { 10 return SearchPage.class; 11 } 17 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/> 1 <!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Strict//ENquot; 2 quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtdquot;> 3 <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> 4 <html xmlns=quot;http://www.w3.org/1999/xhtmlquot; xmlns:wicket=quot;http://wicket.apache.org/quot;> 5 <head> 6 … 11 </head> 12 <body> 13 <wicket:child/> 14 </body> 15 </html> 1 <wicket:extend> 2 <div align=quot;rightquot; class=quot;headerquot; wicket:id=quot;welcomePanelquot;></div> 3 <div class=quot;phoneBookquot; align=quot;centerquot; wicket:id=quot;searchPanelquot;></div> 4 <div class=quot;phoneBookquot; align=quot;centerquot; wicket:id=quot;resultsPanelquot;></div> 5 </wicket:extend> 19 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Features::View Technology • Reuse HTML as it was Java • <wicket:child/> • <wicket:extend/> • <wicket:panel/> 1 <wicket:extend> 2 <div align=quot;rightquot; class=quot;headerquot; wicket:id=quot;welcomePanelquot;></div> 3 <div class=quot;phoneBookquot; align=quot;centerquot; wicket:id=quot;searchPanelquot;></div> 4 <div class=quot;phoneBookquot; align=quot;centerquot; wicket:id=quot;resultsPanelquot;></div> 5 </wicket:extend> 1 <wicket:panel> 2 <table> 3 <tr> 4 <td class=quot;headerquot;><wicket:message key=quot;userquot;/>: <span wicket:id=quot;usernamequot;></span></td> 5 <td class=quot;headerSeperatorquot;>|</td> 6 <td class=quot;headerquot;><a href=quot;#quot; wicket:id=quot;logoutquot;><wicket:message key=quot;logoutquot;/></a></td> 7 </tr> 8 </table> 9 </wicket:panel> 20 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Features::Page Flow • Inside onSubmit (buttons, links and forms) • setResponsePage(SomePage.class); • setResponsePage(somePage); 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(quot;Sorry, …quot;); 11 setModelObject(new User()); 12 } 13 } 21 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Features::Form Binding • Form is a component • So, it is backed up with model 1 private SearchForm(MarkupContainer parent) { 2 super(quot;searchFormquot;, new CompoundPropertyModel(new Contact())); 3 parent.add(this); 4 add(new TextField(quot;namequot;)); 5 TextField emailTextField = new TextField(quot;emailquot;); 6 emailTextField.add(EmailAddressValidator.getInstance()); 7 add(emailTextField); 8 … 9 } 22 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 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(quot;namequot;), quot;namequot;, quot;namequot;)); 4 columns.add(new PropertyColumn(new ResourceModel(quot;department.namequot;), quot;department.namequot;)); 5 columns.add(new TextFieldColumn(new ResourceModel(quot;emailquot;), quot;emailquot;)); 6 return columns.toArray(new IColumn[columns.size()]); 7 } 8 23 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 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 && quot;namequot;.equals(sort.getProperty())) { 7 Collections.sort(sublist); 8 if (!sort.isAscending()) { 9 Collections.reverse(sublist); 10 } 11 } 12 return sublist.iterator(); 13 } 24 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 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(quot;resultsPanelquot;); 3 DataTable contactsTable = new SortablePagedDataTable(quot;contactsTablequot;, 4 getTableColumns(), contactsDataProvider, 10); 5 add(contactsTable); 6 } 25 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 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 && quot;namequot;.equals(sort.getProperty())) { 7 Collections.sort(sublist); 8 if (!sort.isAscending()) { 9 Collections.reverse(sublist); 10 } 11 } 12 return sublist.iterator(); 13 } 26 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Features::Validations (Server) • “Required” validation – just say • Validation errors added to their own <div> (css it at will) 1 public LoginForm(MarkupContainer parent) { 2 super(quot;loginFormquot;, new CompoundPropertyModel(new User())); 3 parent.add(this); 4 add(new TextField(quot;usernamequot;).setRequired(true)); 5 PasswordTextField passwordTextField = new PasswordTextField(quot;passwordquot;); 6 passwordTextField.setRequired(true); 7 add(passwordTextField); 8 FeedbackPanel feedbackPanel = new FeedbackPanel(quot;feedbackquot;); 9 feedbackPanel.setEscapeModelStrings(false); 10 add(feedbackPanel); 11 } 1 <tr> 2 <td colspan=quot;2quot; class=quot;feedbackquot; wicket:id=quot;feedbackquot;/> 3 </tr> 27 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Features::Validations (Server) • Other validations – add Validators to the components • 24 ready validators in wicket-core and wicket-extensions 1 private SearchForm(MarkupContainer parent) { 2 super(quot;searchFormquot;, new CompoundPropertyModel(new Contact())); 3 parent.add(this); 4 add(new TextField(quot;namequot;)); 5 TextField emailTextField = new TextField(quot;emailquot;); 6 emailTextField.add(EmailAddressValidator.getInstance()); 7 … 12 } 28 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 1 private SearchForm(MarkupContainer parent) { 2 super(quot;searchFormquot;, new CompoundPropertyModel(new Contact())); 3 parent.add(this); 4 add(new TextField(quot;namequot;)); 5 TextField emailTextField = new TextField(quot;emailquot;); 6 emailTextField.add(EmailAddressValidator.getInstance()); 7 … 8 AjaxFormValidatingBehavior.addToAllFormComponents(this, quot;onblurquot;); 9 } 30 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Features::AJAX • Use AJAX components instead of non-AJAX ones • Add components to be refreshed 1 private SearchForm(MarkupContainer parent) { 2 super(quot;searchFormquot;, new CompoundPropertyModel(new Contact())); 3 parent.add(this); 4 … 12 add(new AjaxButton(quot;submitquot;, 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, quot;onblurquot;); 24 } 31 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Features::AJAX • JS is generated using Dojo and Script.aculo.us • Automatic fallback to non-js components 1 <script type=quot;text/javascriptquot; 2 src=quot;resources/org.apache.wicket.markup.html.WicketEventReference/wicket-event.jsquot;> 3 </script> 4 <script type=quot;text/javascriptquot; 5 src=quot;resources/org.apache.wicket.ajax.WicketAjaxReference/wicket-ajax.jsquot;> 6 </script> 7 <script type=quot;text/javascriptquot; 8 src=quot;resources/org.apache.wicket.ajax.AbstractDefaultAjaxBehavior/wicket-ajax-debug.jsquot;> 9 </script> 10 <script type=quot;text/javascriptquot; 11 id=quot;wicket-ajax-debug-enablequot;><!--/*--><![CDATA[/*><!--*/ 12 wicketAjaxDebugEnable = true; 13 /*-->]]>*/</script> 14 <script type=quot;text/javascriptquot; 15 src=quot;resources/org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteBehavior/wicket-autocomplete.jsquot;> 16 </script> 17 <script type=quot;text/javascriptquot;><!--/*--><![CDATA[/*><!--*/ 18 Wicket.Event.add(window, quot;domreadyquot;, function() { 19 new Wicket.AutoComplete('department2', 20 '?wicket:interface=:2:searchPanel:searchForm:department::IActivePageBehaviorListener:1:&wicket:ignoreIfNotActive=true', 21 false); 22 }); 23 /*-->]]>*/</script> 32 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Features::AJAX • Great debug utility 33 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 • 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 } 35 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 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 } 36 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar
  • Features::I18N Support • Full I18N of all the application using Resource bundles • Use <wicket:message key=“…quot;/> instead of hard-coded text 1 page.title= 1 page.title=Login 2 username= 2 username=<u>U</u>sername 3 password= 3 password=<u>P</u>assword 4 submit= 4 submit=Login 1 <tr> 2 <td valign=middle align=right width=25%><b><wicket:message key=quot;usernamequot;/></b></td> 3 <td valign=middle> 4 <input class=quot;loginFieldquot; type=quot;textquot; id=quot;usernamequot; size=quot;25quot; tabindex=1 5 accessKey=quot;uquot; wicket:id=quot;usernamequot;> 6 </td> 7 </tr> 37 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 1 public WicketSession(Request request) { 2 super(request); 3 setLocale(new Locale(quot;iwquot;)); 4 } 1 <table class=quot;loginTablequot; border=quot;1quot; style=quot;direction: rtl;quot;> 2 <tr> 3 … 4 </tr> 5 </table> 38 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
  • Summary 40 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
  • Thank You! 47 Copyright AlphaCSP Israel 2008 – Web Framework Playoff Seminar