Advertisement
Advertisement

More Related Content

Recently uploaded(20)

Advertisement

MoroSystems na ostravském CZJUGu o Apache Wicket

  1. Apache Wicket MoroSystems, s.r.o. Pavel Klobása Senior Java Developer pavel.klobasa@morosystems.cz
  2. MoroSystems, s.r.o. • Pobočky Brno a Hradec Králové • Firma s českými vlastníky • 26 zaměstnanců a externistů • Na trhu od roku 2005
  3. MoroSystems, s.r.o. • Odborný weblog VsadNaJavu.cz • Zakázkový vývoj webových aplikací, informačních systémů a portálových řešení • Outsourcing vývoje SW nad Java/J2EE • Implementace a customizace Atlassian JIRA • Internetový startup Hráči.info
  4. Obsah Porovnání s jinými frameworky Komponenty Modely Podpora JavaScriptu a Ajaxu Jak vytvořit RIA
  5. Část první: porovnání s jinými frameworky
  6. Principy webových frameworků MVC Klientský fw Komponentový fw Struts, Spring MVC... Flex, GWT JSF, Tapestry, Wicket Server: celá aplikace Server: REST API Server: celá aplikace Klient: statické HTML Klient: celá aplikace Klient: statické HTML Stav v URL Stav na klientu Stav v komponentách Internet Intranet Intranet Velká zatěž Velká zatěž Střední zatěž
  7. Principy frameworků vs. AJAX MVC Implementace AJAXu jde proti principu MVC. Musíme implementovat vykreslení celé stránky a vykreslení fragmentu stránky zvlášť. Vzniká duplicita kódů... Klientský fw Klient stáhne data přes REST API = základní vlastnost frameworku. Komponentový fw Komponenty „žijí“ na serveru – můžeme je požádat o vykreslení do AJAXové odpovědi – dojde k aktualizaci fragmentu HTML stránky. Pokud fw podporuje AJAX, je jeho použití snadné.
  8. Umí tohle váš framework? ● pracuje s POJO daty ● lze využít generické datové typy ● šablony editovatelné v běžném HTML editoru ● oddělení kódu a šablon ● snadné použití JavaScriptu/AJAXu ● „hezké“ URL, tlačítko Zpět ● podpora pro clustering ● testovatelnost pomocí jednotkových testů
  9. ...tak trochu jako Swing... ● Anonymní třídy ● Model oddělený od komponenty ● Dědičnost ● Kompozice komponent ● (Generické datové typy)
  10. Část druhá: O komponentách
  11. Component WebComponent Hierarchie Label Image komponent WebMarkupContainer Link Border Form Panel FormComponent TreeGrid Button DataGrid CheckBox TabbedPanel FileUpload Další komponenty viz též http://wicket.sourceforge.net/wicket-extensions/ TextField
  12. Grid
  13. Ukázka šablony AddressPanel.html <html xmlns:wicket="http://wicket.apache.org/"> <body> ID komponenty <table class="edit-form"> <wicket:panel> <tr> <th>Adresát:</th> <td><input wicket:id="name" type="text" class="adr"/></td> </tr> <tr> <th>Ulice:</th> <td><input wicket:id="street" type="text"/></td> </tr> <tr> <th>Město:</th> <td><input wicket:id="city" type="text"/></td> </tr> <tr> <th>Země:</th> <td><select wicket:id="country"></select></td> </tr> </wicket:panel> </table> </body> </html>
  14. Je to znovupoužitelná komponta, Ukázka kódu vzniklá jako kompozice komponent public class AddressPanel extends Panel { private static final long serialVersionUID = 1L; public AddressFragmentPanel(String id, IModel<Address> model) { super(id, new CompoundPropertyModel<Address>(model)); add(new TextField<String>("name").setRequired(true)); add(new TextField<String>("street")); Název komponenty odpovídá add(new TextField<String>("city").add(new IValidator(){ názvu atributu modelu public void validate(IValidatable<T> validatable){ String city = (String)getDefaultModelObject(); if (city == null || city.length()<2) { ValidationError error = new ValidationError(); error.setMessage("Bad city name"); validatable.error(error); Anonymní třída není problém } } }); add(new CountryDropDown("country")); } }
  15. IBehavior – modifikace komponenty public interface IBehavior { void beforeRender(Component component); void afterRender(Component component); void onComponentTag(Component comp,ComponentTag tag); boolean isEnabled(Component component); …a několik dalších metod... } Dědičnost komponent umožňuje totéž, ale IBehavior je často elegantnější...
  16. IBehavior – ukázka public class Highlighter extends AbstractBehavior { @Override public void onComponentTag(Component comp,ComponentTag tag) { if (isHighlighted(component)) { tag.getAttributes().put("class","hglt"); } } private boolean isHighlighted(component){ // TODO: implement it } }
  17. IVisitor public class HighlighterUtils { public static void prepareForms(MarkupContainer parent) { parent.visitChildren(FormComponent.class, new IVisitor<FormComponent>(){ public Object component(FormComponent comp){ comp.add(new Highlighter()); return IVisitor.CONTINUE_TRAVERSAL; } }); } } - IBehavior lze opakovaně využít - jedna komponenta může mít více IBehavior
  18. Spring Dependency Injection public class MyComponent extends Component{ @SpringBean ProductDAO productDAO; ... } public class MyApplication extends WebApplication { public void init() { super.init(); addComponentInstantiationListener( new SpringComponentInjector(this)); } <dependency> } <groupId>org.apache.wicket</groupId> <artifactId>wicket-spring</artifactId> <version>${wicket.version}</version> </dependency>
  19. Část druhá: O modelech
  20. Model public interface IModel<T> extends IDetachable{ T getObject(); void setObject(final T object); } Pro srovnání: Model v MVC = mapa objektů Model ve Swingu = ad hoc interface dle komponenty
  21. Některé modely Wicketu AbstractReadOnlyModel – jen pro čtení ResourceModel – lokalizace textů CompoundPropertyModel – jméno atributu=jméno komponenty IChainingModel – zřetězení modelů LoadableDetachableModel – odpojení neserializovatelných objektů
  22. Triviální model Tato implementace je součástí Wicketu: public class Model<T extends Serializable> implements IModel<T> { private static final long serialVersionUID = 1L; private T object; public T getObject() { return object; } public void setObject(final T object) { this.object = object; } } ALE: Model musí být serializovatelný – entity serializované být nesmí (ukládají se pouze do databáze, ne kamsi na disk/síť/cache...) Jak zajístíme vzájemnou aktualizaci dat v modelech více komponent? Jak zajistíme aktualizaci dat při změně v dB?
  23. „Počítaný“ model public class CurrentTimeModel extends AbstractReadOnlyModel<String> { public String getObject() { SimpleDateFormat fmt=new SimpleDateFormat("d.M. hh:mm"); return fmt.format(new Date()); } } Volat metodu je často výhodnější, než uchovávat datový obsah. Můžeme takto rovnou volat DAO...
  24. Model napojený na DAO public class OrderListModel extends AbstractReadOnlyModel<List<Order>> { @SpringBean transient OrderDAO dao; public LoggedUserModel(){ InjectorHolder.getInjector().inject(this); Metoda vrátí } vždy čerstvá data public List<Order> getObject() { return dao.getLoggedUserOrders(); } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); InjectorHolder.getInjector().inject(this); } }
  25. Část třetí: JavaScript a AJAX
  26. JavaScript v komponentě public class HTMLEditor extends TextArea<String>{ @Override protected void onAfterRender() { super.onAfterRender(); getResponse().write(JavascriptUtils.SCRIPT_OPEN_TAG); getResponse().write("makeTinyMCE('" + getMarkupId() + "');"); getResponse().write(JavascriptUtils.SCRIPT_CLOSE_TAG); } } Upozornění: toto je jen ilustrační příklad...
  27. Aktualizace komponenty AJAXem Label clockLabel=new Label("clock", new AbstractReadOnlyModel<String>() { private static final long serialVersionUID = 1L; public String getObject() { SimpleDateFormat fmt=new SimpleDateFormat("d.M. hh:mm:ss"); return fmt.format(new Date()); } }; požadavek vznikl na klientu, add(clockLabel); ale o tom, co se bude dít, add(new AjaxLink<Void>("refresh") { rozhodne server. private static final long serialVersionUID = 1L; @Override public void onClick(AjaxRequestTarget target) { target.addComponent(clockLabel); target.addJavascript("window.defaultStatus='" +Runtime.getRuntime().freeMemory()+"'"); } };
  28. Část pátá: RIA
  29. Rich Internet Application Aplikace běží v prohlížeči a na webovém serveru (=nulové náklady na instalaci na klientech) Napodobuje GUI klient-server aplikace ● ovládání: drag&drop, kontextové menu, ukládání stavu GUI mezi sezeními... ● pokročilé komponenty: datový grid, pulldown menu, autocomplete... ● složitý, často dynamický, layout aplikace Jak na to? Wicket na serveru a JS komponenty na klientu.
  30. Unobtrusive javascript Nevtíravý javascript ● chceme, aby javascript byl „přidanou hodnotou“ a aplikace fungovala i bez něj ● je to best practice pro klasické webové stránky ● užitečný koncept pro napojení serverového komponentového frameworku a klientských javascriptových komponent
  31. Unobtrusive javascript - ukázka HTML JS <div id="tabs"> var tabview = new Y.TabView({srcNode:'#tabs'}); <ul> tabview.render(); <li><a href="#foo">foo</a></li> <li><a href="#bar">bar</a></li> <li><a href="#baz">baz</a></li> </ul> <div> <div id="foo"> <p>foo content</p> </div> <div id="bar"> <p>bar content</p> </div> Toto je ukázkový kód ze stránek YUI3. <div id="baz"> <p>baz content</p> </div> </div> </div>
  32. Porovnání jQuery a YUI jQuery – populární a známý v ČR – krátké, čitelné, elegatní kódy Komponenty v jQuery od různých autorů – rozdílné API, rozdílné licence, nejednotná grafika YUI – používají též velké firmy (eBay, Yahoo) – „nudné“ API Komponenty v YUI jsou součástí fw – podobné API, stejná grafika
  33. Další informace: http://wicket.apache.org http://wicket.sourceforge.net/wicket-extensions http://wicketstuff.org/wicket14 http://wicketstuff.org/grid-example https://cwiki.apache.org/WICKET/spring.html http://developer.yahoo.com/yui/3/examples/
Advertisement