Tworzenie aplikacji internetowych z wykorzystaniem szkieletu Wicket BłaŜej Bukowy, 157489 Wojciech Orzeszyna, 157630
Cel prezentacji Zwrócenie uwagi słuchaczy na webowy framework Apache Wicket Pokazanie na przykładach łatwości tworzenia w Wickecie
Agenda 1. Czym jest Wicket? Historia, cechy charakterystyczne 2. Jak zacząć? Ant, Maven 3. HelloWorld 4. Koncepcje Wicket 5. WicketTester 6. Wicket Bench 7. Integracja z innymi frameworkami Spring, Hibernate 8. Co słychać u konkurencji? 9. Kto tego uŝywa? 10. Wady i zalety 11. Wsparcie 12. Bibliografia
Czym jest Wicket? Lekki, oparty na komponentach opensource'owy framework do budowy aplikacji webowych za pomocą Javy i HTML-a
Historia 2004 start projektu (Jonathan Locke) 2005 JavaOne'05 (wersja 1.0) 2006 inkubacja w ASF (wersja 1.2) 2007 status Top Level Projects w ASF 2008 wersja 1.3 2009 wersja 1.4 2010 wersja 1.4.7
Cechy charakterystyczne Wicketa Tylko JAVA i HTML Komponenty i obiekty Separacja kodu od widoku Absolutne minimum konfiguracji w XML Wbudowany AJAX (JavaScript) Przejrzyste zarządzanie sesjami Przyjazne adresy URL
Cechy charakterystyczne Wicketa Rozwiązanie problemu przycisku wstecz Integralność z innymi frameworkami i bibliotekami (Spring, Hibernate + inne) Rozbudowane, gotowe do uŝycia komponenty (ponad 200) wybieranie daty, edytor tekstu, Google Maps panel z kartami, nawigacja, drzewo
Co to oznacza w praktyce? Pisanie aplikacji w Apache Wicket bardziej przypomina pisanie aplikacji desktopowej niŝ aplikacji webowej Jasny podział zakresu prac między programistę i projektanta wyglądu stron Szybki start tylko znane technologie
Jak zacząć? Wymagania wstępne: JDK 5 Java IDE Kontener servletów Maven lub Ant
Jak zacząć? - Ant Biblioteki: wicket.jar servletapi-2.3.jar slf4j-api.jar jetty.jar jetty-util.jar slf4j-log4j12.jar log4j.jar
Jak zacząć? - Ant build.xml
Jak zacząć? - Ant build.xml
Jak zacząć? - Ant build.xml
Jak zacząć? Maven http://wicket.apache.org/quickstart.html mvn archetype:create DarchetypeGroupId=org.apache.wicket DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=1.4.8 DgroupId=com.mycompany -DartifactId=myproject <dependency> <groupid>org.apache.wicket</groupid> <artifactid>wicket</artifactid> <version>1.4.8</version> </dependency> pom.xml
Jak zacząć?
Jak zacząć? Wicket in Action Bonus Chapter 15 Setting up a Wicket project http://www.manning.com/dashorst/wicket_bonus-chapter15.pdf
HelloWorld Budowa strony: Plik *.html Plik *.java (o tej samej nazwie) Powiązanie: wicket:id
HelloWorld <h1 wicket:id="msg">[tu zmienimy]</h1> + HelloWorld.html add(new Label("msg", "Hello World!")) = HelloWorld.java <h1>hello World!</h1>
Koncepcje Wicket Aplikacja Sesja RequestCycle Komponenty Zachowania Model
Koncepcje Wicket Aplikacja Kontener najwyŝszego poziomu, przechowuje: Komponenty Znaczniki Pliki konfiguracyjne Właściwości Inicjalizacja i konfiguracja UŜycie specyficznych tagów Wicket Określenie strony startowej Konfiguracja DAO (dla uŝywających Springa) Fabryki dla obiektów (np. Session, RequestCycle, Security) Konfiguracja w web.xml Plik WebApplication.java
Koncepcje Wicket Aplikacja <filter> <filter-name>wicket</filter-name> <filter-class> org.apache.wicket.protocol.http.wicketfilter </filter-class> <init-param> <param-name>applicationclassname</param-name> <param-value>example.myapplication</param-value> </init-param> <load-on-startup>1</load-on-startup> </filter>
Koncepcje Wicket Sesja Abstrakcja sesji uŝytkownika Typowo trzymana w HttpSession Przypisane do wątków Silnie typowana class MySession extends WebSession { } private ShoppingCart cart; public ShoppingCart getcart() { } public void setcart(shoppingcart cart) { } Zawiera komponenty i historię stron
Koncepcje Wicket Sesja 1. PrzeciąŜenie metody newsession w WicketApplication.java @Override public Session newsession(request request, Response response) { } return new KlasaSesji(WicketApplication.this, request);
Koncepcje Wicket Sesja 2. Utworzenie klasy przechowującej sesję public final class KlasaSesji extends WebSession { } private boolean stansesji; protected KlasaSesji(WebApplication application, Request request) { super(request); stansesji = false; } public void setstansesji(boolean _ss) { stansesji = _ss; } public boolean getstansesji() { return stansesji; }
Koncepcje Wicket Sesja 3. Dostęp do obiektu sesji PlikSesji session = (PlikSesji) getsession(); session.setstansesji(true);
Koncepcje Wicket - RequestCycle Kroki podejmowane przy kaŝdym Ŝądaniu: Stworzenie obiektu RequestCycle Dekodowanie Ŝądania Identyfikacja celu Ŝądania (jaka strona, komponent?) Przetworzenie zdarzeń (onclick, onsubmit) Wygenerowanie odpowiedzi (strona, komponent, obrazek, pdf...) Sprzątanie
Koncepcje Wicket - RequestCycle Dwa typy Ŝądań: Stanowe Związane z konkretną sesją uŝytkownika Nie da się zrobić zakładki Bezstanowe Niekoniecznie związane z konkretną sesją MoŜna uczynić z nich zakładki
Koncepcje Wicket - RequestCycle
Koncepcje Wicket Komponent Podstawowy klocek w aplikacji Potrafi się wyrysować Odbiera zdarzenia Łatwo rozszerzalny i łatwy do ponownego wykorzystania Dostępne ponad 220 gotowych komponentów w Wicket core i Wicket extensions! Główne komponenty odpowiadają plikowi HTML Podkomponenty odpowiadają elementom HTML Hierarchie w kodzie i widoku muszą się zgadzać!
Koncepcje Wicket Komponent
Koncepcje Wicket Komponent Połączenie komponentu z widokiem w HTMLu za pomocą wicket:id <h1 wicket:id= msg >[tu zmienimy]</h1> HTML new Label( msg, Hello, World! ); Java MoŜna usunąć wicket:id z wynikowej odpowiedzi
Koncepcje Wicket Komponent (Link) <a href="#" wicket:id="link">click</a> HTML Link link = new Link("link") { }; @Override public void onclick() { } add(link); //do something setresponsepage(new NewPage()); Java
Koncepcje Wicket Komponent (AjaxLink) <a wicket:id="link">click</a> HTML AjaxLink link = new AjaxLink("link") { }; public void onclick(ajaxrequesttarget t){ } add(link); //do something t.addcomponent(somecomponent); t.appendjavascript("effects.fade('foo');"); Java
Koncepcje Wicket Zachowania Zachowania to rodzaj wtyczek do komponentów Mogą zmieniać kod HTML generowany przez komponent item.add(new AbstractBehavior() { }); public void oncomponenttag(component component, ComponentTag tag) { tag.put("class", css = (((Item)component).getIndex() % 2 == 0)? "even" : "odd"); } Wyśjcie: <tr class= odd > </tr> <tr class= even > </tr>
Koncepcje Wicket - Zachowania Nie tylko zmiana atrybutów Dodawanie JavaScriptowych zdarzeń Dodawanie zachowania w stylu Ajax component.add( new AjaxSelfUpdatingBehavior( Duration.seconds(1) ) );
Koncepcje Wicket Model KaŜdy komponent ma swój model, który utrzymuje jego stan Model jest połączeniem komponentu z naszymi POJOs
Koncepcje Wicket Model Leniwe wiązanie w Javie? Nie aktualizuje wartości new TextField( txt, person.getname()) Trzeba uwaŝać na puste referencje new Label( street, person.getaddress().getstreet()) Rozwiązanie: wyraŝenia w stylu OGNL/EL Przyłączalne i odłączalne modele new Label("lastname", customer.getname()); = new Label("lastname", new Model(customer.getName()));
Koncepcje Wicket Model add(new Label("street", (cust==null cust.getaddress()==null)? "" : cust.getaddress().getstreet()); vs add(new Label("street", new PropertyModel(customer,"address.street"))); vs setmodel(new CompoundPropertyModel(customer)); add(new Label("address.street ");
Koncepcje Wicket Model public class MyForm extends Form { } public MyForm(String id) { } super(id); Customer customer = new Customer(); setmodel(new Model(customer)); add(new TextField("name", new PropertyModel(customer, "name"))); add(new TextField("street", new PropertyModel(customer, address.street"))); protected void onsubmit() { } Customer customer = (Customer)getModelObject(); String street = customer.getaddress().getstreet(); //
WicketTester Klasa słuŝąca do testów jednostkowych komponentów JUnit / TestNG Intuicyjne modelowanie sposobu uŝywania aplikacji przez uŝytkownika Testowalne są równieŝ akcje AJAX
WicketTester - przykład WicketTester wickettester = new WicketTester(new WicketApplication()); wickettester.startpage(fileinfopage.class); wickettester.assertrenderedpage(loginpage.class); FormTester formtester = wickettester.newformtester("signinpanel:signinform"); formtester.setvalue("username", gosc"); formtester.setvalue("password", haslo123"); formtester.submit(); wickettester.assertrenderedpage(fileinfopage.class); wickettester.assertlabel("message", Zalogowany jako gosc");
Wicket Bench Plugin do Eclipse a Adres do instalacji bezpośrednio z Eclipse: http://www.laughingpanda.org/svn/wicket-bench/trunk/wicket-bench-site
Wicket Bench - features Poprawiony edytor Wizardy dla projektów i paneli Wicketa Generator formularzy Quick fixes Parser bloków wicket:id w plikach HTML Integracja z Selenium
Integracja ze Springiem Więcej warstw! Dependency Injection Dodatkowe komponenty
Integracja ze Springiem Jak? XML, Bean, WicketApplication.java public class WicketInActionApplication extends WebApplication { private ApplicationContext ctx; @Override protected void init() { } ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Public DiscountsService getdiscountservice() { } return (DiscountsService) BeanFactoryUtils.beanOfType(ctx, DiscountsService.class);
Integracja z Hibernate Most między OOP a ORM Definiowanie encji Mapowanie obiektów
Integracja z Hibernate Persistence.xml <persistence> <persistence-unit name="wicketpersistencemanager" transactiontype="resource_local"> <class>com.apress.wicketbook.shop.model.book</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.hsqldialect"/> <property name="hibernate.connection.driver_class"value="org.hsqldb.jdbcdriver"/> <property name="hibernate.connection.username" value="sa"/> <property name="hibernate.connection.password" value=""/> <property name="hibernate.connection.url" value="jdbc:hsqldb:."/> <property name="hibernate.max_fetch_depth" value="3"/> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> <property name="hibernate.show_sql">true</property> <property name="hibernate.jdbc.batch_size" value="0"/> </properties> </persistence-unit> </persistence>
Co słychać u konkurencji?
Co słychać u konkurencji? Wbudowane wsparcie dla Ajaxa: JSF: Brak, wykorzystuje ICEfaces i Ajax4JSF Stripes: Brak Struts 2: wbudowana biblioteka DOJO, pluginy dla GWT Spring MVC: Brak, wykorzystuje DWR i Spring MVC Extras Tapestry: wbudowana biblioteka DOJO Wicket: wbudowana biblioteka DOJO
Co słychać u konkurencji? Przyjazne adresy URL: JSF: wszystko przesyłane POST-em, nie ma mowy o URLach Stripes: Tak Struts 2: namespace y - tak Spring MVC: Tak Tapestry: Nie Wicket: Tak
Co słychać u konkurencji? Walidacja po stronie uŝytkownika: JSF: Brzydkie, ale konfigurowalne domyślne komunikaty Stripes: Walidacja w Javie nie ma walidacji po stronie klienta Struts 2: Tak, wykorzystuje OGNL Spring MVC: Tak, wykorzystuje Commons Validator Tapestry: Tak, bardzo dobre domyślne komunikaty Wicket: Walidacja w Javie nie ma walidacji po stronie klienta
Co słychać u konkurencji? Testowalność: JSF: Brzydkie, ale konfigurowalne domyślne komunikaty Stripes: Servlet API Mocks, MockRoundtrip Struts 2: EasyMock, jmock Spring MVC: EasyMock, jmock, SpringMock Tapestry: Trudne testowanie klasy stron są abstrakcyjne Wicket: WicketTester bardzo dobre rozwiązanie
Co słychać u konkurencji?
Co słychać u konkurencji? Liczba ksiąŝek na Amazon.com Wicket Tapestry Struts 2 Stripes Spring MVC JSF 0 5 10 15 20 25
Co słychać u konkurencji? Dostępne narzędzia Wicket Tapestry Struts 2 Stripes Spring MVC JSF 0 5 10 15
Co słychać u konkurencji? Liczba ofert pracy w ostatnich 3 miesiącach Wicket Tapestry Struts 2 Stripes Spring MVC JSF 0 500 1000 1500 2000 2500 3000 3500 www.itjobswatch.co.uk
Co słychać u konkurencji?
Co słychać u konkurencji?
Kto tego uŝywa? http://fabulously40.com Rails Wicket
Kto tego uŝywa? http://www.meetmoi.com
Kto tego uŝywa? http://www.avigo.de Wicket + Hibernate + Spring
Zalety Wicketa Łatwość tworzenia komponentów i ich ponownego uŝywania Brak potrzeby konfiguracji XML śeby zacząć wystarczy znajomość Javy Separacja kodu Java od HTML MoŜliwość integracji z innymi frameworkami, jak Spring MVC czy Hibernate Rosnąca popularność i duŝa społeczność
Wady Wicketa DuŜo kodu w Javie moŝe być trudne do utrzymania Projektanci IU muszą pamiętać o znacznikach Wicketa MoŜe być za wolny dla bardzo dynamicznych stron Tylko widok i model brak kontrolera Nie naleŝy do standardu, wciąŝ jeszcze mała popularność Trzeba znać Javę
Wsparcie Listy mailingowe: Wicket Users Wicket Developers Wicket Announcements Wicket Commits IRC (##wicket@irc.freenode.net) Blogi Google Dokumentacja https://cwiki.apache.org/wicket/documentation-index.html
Bibliografia Wicket in Action - Martijn Dashorst, Eelco Hillenius, wydawnictwo Manning Publications (2008) Enjoying Web Development with Wicket - Kent Tong (2007) Pro Wicket - Karthik Gurumurthy, wydawnictwo Apress (2006) https://cwiki.apache.org/wicket/ http://www.theserverside.com/tt/articles/article.tss?l=i ntroducingapachewicket http://www.slideshare.net/dashorst/wicket-inaction http://www.ibm.com/developerworks/web/library/waaj-wicket/index.html
Część praktyczna Przykład na Ŝywo