SlideShare une entreprise Scribd logo
1  sur  33
Télécharger pour lire hors ligne
Apache Wicket
MoroSystems, s.r.o.
Pavel Klobása
Senior Java Developer
pavel.klobasa@morosystems.cz
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
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
Obsah
  Porovnání s jinými frameworky
  Komponenty
  Modely
  Podpora JavaScriptu a Ajaxu
  Jak vytvořit RIA
Část první: porovnání s
  jinými frameworky
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ěž
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é.
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ů
...tak trochu jako Swing...

   ● Anonymní třídy
   ● Model oddělený od komponenty

   ● Dědičnost

   ● Kompozice komponent

   ● (Generické datové typy)
Část druhá:
O komponentách
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
Grid
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>
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"));
    }
}
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ší...
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
     }
 }
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
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>
Část druhá:
O modelech
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
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ů
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?
„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...
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);
    }
}
Část třetí:
JavaScript a AJAX
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...
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()+"'");
     }
  };
Část pátá: RIA
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.
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
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>
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
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/

Contenu connexe

En vedette

THE DESIGN OF IONIC CAPITAL
THE DESIGN OF IONIC CAPITALTHE DESIGN OF IONIC CAPITAL
THE DESIGN OF IONIC CAPITALAmanda Laoupi
 
Fruizione del patrimonio artistico e culturale
Fruizione del patrimonio artistico e culturaleFruizione del patrimonio artistico e culturale
Fruizione del patrimonio artistico e culturaleTurismoProvPC
 
ตารางวันเวลาเรียนการสืบค้นสารสนเทศ
ตารางวันเวลาเรียนการสืบค้นสารสนเทศตารางวันเวลาเรียนการสืบค้นสารสนเทศ
ตารางวันเวลาเรียนการสืบค้นสารสนเทศlibrarynkc
 
Permainan pecahan rafly 2003
Permainan pecahan rafly 2003Permainan pecahan rafly 2003
Permainan pecahan rafly 2003fsnuri
 
Complete Arabesque Collection Catalogue
Complete Arabesque Collection CatalogueComplete Arabesque Collection Catalogue
Complete Arabesque Collection CatalogueDoronMerdinger
 
Дебатът между Айнщайн и Бор по основите на квантовата механика
Дебатът между Айнщайн и Бор по основите на квантовата механикаДебатът между Айнщайн и Бор по основите на квантовата механика
Дебатът между Айнщайн и Бор по основите на квантовата механикаVasil Penchev
 
Bajo La Lupadel Consumidor 186[1]
Bajo La Lupadel Consumidor 186[1]Bajo La Lupadel Consumidor 186[1]
Bajo La Lupadel Consumidor 186[1]guest0ddcfc0
 
Genesis 2 greek
Genesis 2   greekGenesis 2   greek
Genesis 2 greekjreisig
 
Биофизика2011-2
Биофизика2011-2Биофизика2011-2
Биофизика2011-2nemelev
 
Lucrècia: del mite a l'art
Lucrècia: del mite a l'artLucrècia: del mite a l'art
Lucrècia: del mite a l'artmanhoh
 
Chasis De Motocicletas
Chasis De MotocicletasChasis De Motocicletas
Chasis De Motocicletasmaxireloco
 
Bedrijfspresentatie
BedrijfspresentatieBedrijfspresentatie
Bedrijfspresentatielouisa_stern
 

En vedette (20)

THE DESIGN OF IONIC CAPITAL
THE DESIGN OF IONIC CAPITALTHE DESIGN OF IONIC CAPITAL
THE DESIGN OF IONIC CAPITAL
 
T.poyo
T.poyoT.poyo
T.poyo
 
Teoria i 02-retorica
Teoria i 02-retoricaTeoria i 02-retorica
Teoria i 02-retorica
 
Fruizione del patrimonio artistico e culturale
Fruizione del patrimonio artistico e culturaleFruizione del patrimonio artistico e culturale
Fruizione del patrimonio artistico e culturale
 
Softwarelibre
SoftwarelibreSoftwarelibre
Softwarelibre
 
ตารางวันเวลาเรียนการสืบค้นสารสนเทศ
ตารางวันเวลาเรียนการสืบค้นสารสนเทศตารางวันเวลาเรียนการสืบค้นสารสนเทศ
ตารางวันเวลาเรียนการสืบค้นสารสนเทศ
 
Historico estrutura 2011
Historico estrutura 2011Historico estrutura 2011
Historico estrutura 2011
 
Permainan pecahan rafly 2003
Permainan pecahan rafly 2003Permainan pecahan rafly 2003
Permainan pecahan rafly 2003
 
Complete Arabesque Collection Catalogue
Complete Arabesque Collection CatalogueComplete Arabesque Collection Catalogue
Complete Arabesque Collection Catalogue
 
Дебатът между Айнщайн и Бор по основите на квантовата механика
Дебатът между Айнщайн и Бор по основите на квантовата механикаДебатът между Айнщайн и Бор по основите на квантовата механика
Дебатът между Айнщайн и Бор по основите на квантовата механика
 
Proyecto sena
Proyecto senaProyecto sena
Proyecto sena
 
Bajo La Lupadel Consumidor 186[1]
Bajo La Lupadel Consumidor 186[1]Bajo La Lupadel Consumidor 186[1]
Bajo La Lupadel Consumidor 186[1]
 
Voy a seguir_(1)
Voy a seguir_(1)Voy a seguir_(1)
Voy a seguir_(1)
 
Genesis 2 greek
Genesis 2   greekGenesis 2   greek
Genesis 2 greek
 
Биофизика2011-2
Биофизика2011-2Биофизика2011-2
Биофизика2011-2
 
Tolerancia
ToleranciaTolerancia
Tolerancia
 
Lucrècia: del mite a l'art
Lucrècia: del mite a l'artLucrècia: del mite a l'art
Lucrècia: del mite a l'art
 
Chasis De Motocicletas
Chasis De MotocicletasChasis De Motocicletas
Chasis De Motocicletas
 
Bedrijfspresentatie
BedrijfspresentatieBedrijfspresentatie
Bedrijfspresentatie
 
Alunos aula pa
Alunos aula paAlunos aula pa
Alunos aula pa
 

Similaire à MoroSystems na ostravském CZJUGu o Apache Wicket

Rozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCRozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCtopascz
 
Rozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCRozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCtopascz
 
Polymer project presentation
Polymer project presentationPolymer project presentation
Polymer project presentationjskvara
 
Nette framework - How to compile an extensible di container
Nette framework - How to compile an extensible di containerNette framework - How to compile an extensible di container
Nette framework - How to compile an extensible di containerFilip Procházka
 
Android Development for Phone and Tablet
Android Development for Phone and TabletAndroid Development for Phone and Tablet
Android Development for Phone and TabletTomáš Kypta
 
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)Martin Zeman
 
MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)
MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)
MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)Péhápkaři
 
INPTP Rekapitulace
INPTP Rekapitulace INPTP Rekapitulace
INPTP Rekapitulace Jan Hřídel
 
2007 Technologie Pro Tvorbu Java Enterprise Aplikací
2007 Technologie Pro Tvorbu Java Enterprise Aplikací2007 Technologie Pro Tvorbu Java Enterprise Aplikací
2007 Technologie Pro Tvorbu Java Enterprise AplikacíMartin Ptáček
 
Technologie užívané při vývoji velkých e-shopů
Technologie užívané při vývoji velkých e-shopůTechnologie užívané při vývoji velkých e-shopů
Technologie užívané při vývoji velkých e-shopůPeckaDesign.cz
 
Czechitas - školení PHP/Symfony MicroKernel
Czechitas - školení PHP/Symfony MicroKernelCzechitas - školení PHP/Symfony MicroKernel
Czechitas - školení PHP/Symfony MicroKernelDennis Fridrich
 
ASP.NET MVC 3 and SQL Server interoperability overview [CZ]
ASP.NET MVC 3 and SQL Server interoperability overview [CZ]ASP.NET MVC 3 and SQL Server interoperability overview [CZ]
ASP.NET MVC 3 and SQL Server interoperability overview [CZ]Vítězslav Šimon
 
JavaScript v GTM - Measure Camp Brno 2017
JavaScript v GTM - Measure Camp Brno 2017JavaScript v GTM - Measure Camp Brno 2017
JavaScript v GTM - Measure Camp Brno 2017Michal Blažek
 

Similaire à MoroSystems na ostravském CZJUGu o Apache Wicket (20)

Rozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCRozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVC
 
Rozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVCRozšiřitelnost ASP.NET MVC
Rozšiřitelnost ASP.NET MVC
 
ASP.NET 3.5 / futures
ASP.NET 3.5 / futuresASP.NET 3.5 / futures
ASP.NET 3.5 / futures
 
Django
DjangoDjango
Django
 
ADO.NET
ADO.NETADO.NET
ADO.NET
 
Polymer project presentation
Polymer project presentationPolymer project presentation
Polymer project presentation
 
TNPW2-2011-03
TNPW2-2011-03TNPW2-2011-03
TNPW2-2011-03
 
Nette framework - How to compile an extensible di container
Nette framework - How to compile an extensible di containerNette framework - How to compile an extensible di container
Nette framework - How to compile an extensible di container
 
Android Development for Phone and Tablet
Android Development for Phone and TabletAndroid Development for Phone and Tablet
Android Development for Phone and Tablet
 
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
 
MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)
MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)
MicroKernel aneb spatny nazev pro Helper (5. sraz pratel Symfony)
 
INPTP Rekapitulace
INPTP Rekapitulace INPTP Rekapitulace
INPTP Rekapitulace
 
2007 Technologie Pro Tvorbu Java Enterprise Aplikací
2007 Technologie Pro Tvorbu Java Enterprise Aplikací2007 Technologie Pro Tvorbu Java Enterprise Aplikací
2007 Technologie Pro Tvorbu Java Enterprise Aplikací
 
Technologie užívané při vývoji velkých e-shopů
Technologie užívané při vývoji velkých e-shopůTechnologie užívané při vývoji velkých e-shopů
Technologie užívané při vývoji velkých e-shopů
 
Czechitas - školení PHP/Symfony MicroKernel
Czechitas - školení PHP/Symfony MicroKernelCzechitas - školení PHP/Symfony MicroKernel
Czechitas - školení PHP/Symfony MicroKernel
 
Clean code
Clean codeClean code
Clean code
 
ASP.NET MVC 3 and SQL Server interoperability overview [CZ]
ASP.NET MVC 3 and SQL Server interoperability overview [CZ]ASP.NET MVC 3 and SQL Server interoperability overview [CZ]
ASP.NET MVC 3 and SQL Server interoperability overview [CZ]
 
JavaScript v GTM - Measure Camp Brno 2017
JavaScript v GTM - Measure Camp Brno 2017JavaScript v GTM - Measure Camp Brno 2017
JavaScript v GTM - Measure Camp Brno 2017
 
R85 Designer Tcl
R85 Designer TclR85 Designer Tcl
R85 Designer Tcl
 
R85 Designer
R85 DesignerR85 Designer
R85 Designer
 

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)
  • 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>
  • 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); } }
  • 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()+"'"); } };
  • 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