Introduktion til GWT

Page 1

Introduktion til GWT

Introduktion til GWT Copyright Š Lund & Bendsen A/S

1


Om underviseren • Jesper Tejlgaard – – – –

jesper@lundogbendsen.dk linkedin.com/in/jespertejlgaard Cand.polyt fra Danmarks Tekniske Universitet Konsulent og instruktør indenfor Java og Java EE.

• Specialist i Java og Java EE • Lund&Bendsens Web specialist – Senest med i teknisk review af bank PM system med GWT front-end Introduktion til GWT Copyright © Lund & Bendsen A/S

2


Om denne introduktion • Indhold – Hvad er GWT? – Litteratur og værktøjer – Den første applikation – Sådan gøres det

Kom godt i gang

• Forklaring af begreberne • Tag de rigtige valg med det samme.

Introduktion til GWT Copyright © Lund & Bendsen A/S

3


Introduktion til GWT • • • •

Hvad er GWT Litteratur og værktøjer Den første applikation Sådan gøres det

Introduktion til GWT Copyright © Lund & Bendsen A/S

4


Hvad er GWT ? • GWT er både et klient- og server-baseret Ajax-framework, men det foretrækkes at lave kode til klienten. • GWT indeholder både Ajax-kerneydelser og visuelle elementer til Widgets mm. • Java foretrækkes som udviklingsprog, men klientkoden compileres til JavaScript. • Fleksibelt mht. arkitektur og design – – – – –

Hård wirering vs. løs wirering med Event mekanisme One page design vs flere sider i applikationen. UI Layout i HTML / XML / Java. Klient server kommunikation – RPC/HTTP+JSON ... Introduktion til GWT Copyright © Lund & Bendsen A/S

5


Java til JavaScript compilering Udvikling

Produktion

Client

Client JavaScript

Java Shared

compile

Java

Shared JavaScript / Java

Java Server

Java Server

Typisk GWT arkitektur. Dog er Java ikke krævet på serverside Introduktion til GWT Copyright © Lund & Bendsen A/S

6


Ulemper/begrænsninger ved GWT • Kun et begrænset antal klasser er portable til JavaScript – Primært klasserne i java.lang og java.util – Men i praksis vil vi alligevel nok foretrække at mere avancerede ting kører på serveren ☺

• Vi kan ikke benytte tredieparts JAR-filer til klientsiden. Introduktion til GWT Copyright © Lund & Bendsen A/S

7


Hvilke slags webapps egner GWT sig til? • Rige brugergrænseflader med masser af interaktion. • Wizards og lign., hvor brugeren igennem et antal trin modificerer en model. • Performance-krævende applikationer, hvor antallet af server-roundtrips kan nedsættes ved at skubbe logik ud på klienten.

Introduktion til GWT Copyright © Lund & Bendsen A/S

8


Introduktion til GWT • • • •

Hvad er GWT Litteratur og værktøjer Den første applikation Sådan gøres det

Introduktion til GWT Copyright © Lund & Bendsen A/S

9


Litteratur • Bøger – – – –

Nyeste bog på Amazon er fra 2010 og håbløst bagud. Ingen af dem afdækker vigtigste features i GWT 2.1 Nye GWT version releases i hastigt tempo Der kommer dog en ny bog i 2012 ===>

• Brug GWTs egen Developers Guide – https://developers.google.com/web-toolkit/doc/latest/DevGuide – API, – Komponent demo Skal læses kritisk. Er skrevet på – Artikler forskellige tidspunkter i GWTs udvikling af forskellige udviklere – Tutorials og stikker derfor i mange retninger – ... Introduktion til GWT Copyright © Lund & Bendsen A/S

10


Værktøjer til GWT • GWT skrives i Java, så... – – – –

IDE: Eclipse, STS, Netbeans Maven, Ant, ... Junit Google App Engine

• GWT tools: – kommando-linien: webAppCreator, junitCreator mfl. – Letvægts test-server: Development mode browser – Google Plugin for Eclipse med Google Designer

• Tredjeparts: – GWT-Platform, gwt-dispatch, gwt-json-commandpattern, SmartGWT, GWT-Ext, Ext GWT, Introduktion til GWT Copyright © Lund & Bendsen A/S

11


Google Plugin for Eclipse • Google Plugin for Eclipse indeholder funktionalitet til at gøre livet med GWT lettere • Gør det let at skabe et GWT-projekt (dog med samme uhensigtsmæssige prædefinerede indhold som webAppCreator) • Gør det let at starte Development mode browser. • Indeholder hele GWT, så vi ikke behøver at downloade denne separat fra GWT's hjemmeside. • Findes online på: http://code.google.com/eclipse/

Introduktion til GWT Copyright © Lund & Bendsen A/S

12


Introduktion til GWT • • • •

Hvad er GWT Litteratur og værktøjer Den første applikation Sådan gøres det

Introduktion til GWT Copyright © Lund & Bendsen A/S

13


Oprettelse af projekt – Web applikation • Google Plugin for eclipse leverer en simpel projektmodel, som benyttes vha File > New > Web Application Projekt • Husk at slå Google App Engine fra (den skal vi ikke bruge)

Introduktion til GWT Copyright © Lund & Bendsen A/S

14


Oprettelse af projekt – Web applikation • Resultatet af forrige dialog ses til højre. (Find det under Other Projects) • Projektet fødes med en "Greeting service" som vi ikke skal bruge i denne opgave. • MyProject.html og MyProject.css definerer det statiske indhold på siden (flad html + flad css). • Endelig er der klassen MyProject.java, som implementerer interfacet EntryPoint som er den vi vil arbejde med nu. Introduktion til GWT Copyright © Lund & Bendsen A/S

15


EntryPoint • EntryPoint-interfacet definerer metoden onModuleLoad, hvorfra vores GWT-app. "starter". • I onModuleLoad metoden kan vi vha. alm. Javakode specificere opførsel for web-siden. • I sample applikation er alt GWT klientkoden skrevet i onModuleLoad metoden. • Reelt skrives klientkoden i mange klasser – widgets, komponenter, mm og ”glue” og opstartskode stå i onModuleLoad. Introduktion til GWT Copyright © Lund & Bendsen A/S

16


GWT Designer • Åben EntryPoint-klassen ved at højreklikke på den og vælge open with > GWT Designer. • GWT Designer initialiseres for projektet hvorefter du får ...

Introduktion til GWT Copyright © Lund & Bendsen A/S

17


(classic) Development mode • Gør det muligt under udvikling at – at bruge Java debug værktøjer – at se vores applikation i en browser – at bygge projektet hurtigt

• Det gøres ved – at koden eksekveres som Java byte kode på en JVM – at installere et GWT browser plugin, som gør det muligt at se applikationen i en browser

• Resultat: "view-code-view-code" programmeringsstil • Debug: Debug As -> Web Application Introduktion til GWT Copyright © Lund & Bendsen A/S

18


Super Dev mode • • • •

Kompiler Java til JavaScript på en code server Installér: http://jeff-davis.blogspot.dk/2012/07/setting-up-gwt-25s-superdevmode.html Mere: https://developers.google.com/web-toolkit/articles/superdevmode ´Konsekvenser – – – –

Browser plugin ikke nødvendigt Debug Java kode i browseren Web server Bedre performance HTML pages …og mere…

Browser

request

Code server Java Source code

GWT compiler

http://localhost:9876/hello/ hello.nocache.js request Introduktion til GWT Copyright © Lund & Bendsen A/S

19


Kørsel/debug af applikationen • Højreklik på projektet og vælg: – Run As -> Web Application – Run As -> Web Application (running on ...)

• Eller tilsvarende for debug. – Debug As -> Web Application – Debug As -> Web Application (running ...)

• Som bruger hhv medfølgende Jetty server, eller egen eksternt konfigureret webserver Introduktion til GWT Copyright © Lund & Bendsen A/S

20


Hvordan gør man? I konsollen kan du følge med i hvad der bliver klikket på i browseren

Refresh her når du har lavet ændringer i koden

Url’en hvor vi kan se vores applikation i developer mode. Højreklik for at vælge browser (eller bruges default) og husk at browseren skal have Google Web Toolkit developer plugin Introduktion til GWT Copyright © Lund & Bendsen A/S

21


GWT.log(String, Throwable)

• Benyttes til logging i client-side kode. • Er kun gældende i Development Mode. • I Production Mode ignoreres disse kald simpelthen af compileren!

Introduktion til GWT Copyright © Lund & Bendsen A/S

22


Kompilering af Java til JavaScript GWT's compiler genererer en fuldt JavaScript klient applikation ud fra et fuldkomment Java-projekt. Din kode hostes af serveren, men eksekverer ude på klienten! GWT's compiler understøtter flg. script "styles": •Obfuscate (default - ulæseligt og komprimeret) •Pretty (læseligt, men uden klassenavne) •Detailed (fuldt læseligt) function hello(name) { var greeting = "Hello " + name; return greeting; }

function a(b){b="Hello "+b;return b;}

Introduktion til GWT Copyright © Lund & Bendsen A/S

23


Introduktion til GWT • • • •

Hvad er GWT Litteratur og værktøjer Den første applikation Sådan gøres det

Introduktion til GWT Copyright © Lund & Bendsen A/S

24


Case: Netbutik • GWT-Solution-07-ActivitiesAndPlaces • En løsning fra en øvelse på GWT kurset – En af de senere øvelser – Men ikke nær så kompliceret, som et projekt setup

• Demonstrer nogen af de ting, vi skal se på – – – – – –

Composite Widgets UiBinder Remote Procedure Call (RPC) MVP og Activities and Places Factories / Gin

Introduktion til GWT Copyright © Lund & Bendsen A/S

25


Brug GWTs egne UI Widgets Data widgets:

Paneler kan indeholde andre widgets: Introduktion til GWT Copyright Š Lund & Bendsen A/S

26


Byg jeres egne widgets: Composite UIObject Byg separate Widget-klasser til de større dele af applikationen.

•Separations of concern •Giver god strukturMenuItem •DRY/genbrugelighed

TreeItem

Frame Label gerne MenuBar Hyperlink Pak en eksisterende Tabel ind i din egen MyTabel.Image

<interface> EventListener

ListBox

0-*

Widget

FocusWidget

FileUpload

Composite

Tree

–mindsker vedligeholdelse, HTML InlineLabel NamedFrame –forbedrer udvidbarheden. RichTextArea TextBoxBase Eksempler

<interface> HasHandlers

DatePicker

ButtonBase

Anchor

SuggestBox

DateBox

- shoppingbasket, productlist, ... TextBox

TextArea

CheckBox

RadioButton

Button

CustomButton

Introduktion til GWT

ToggleButton

Copyright © Lund & Bendsen A/S

PushButton

MyWidget

27


Programmatisk vs markup-baseret UI <panel> <button label="OK" /> </panel>

Panel p = new Panel(); Button b = new Button("OK"); p.add(b);

• I skal tage et valg mht. hvordan layout udvikles. • Programmatiske UI – udvikles i et general purpose sprog (som Java), hvor markupbaserede har deres eget sprog tilpasset dét formål. – GWT lavet til dette. – layout kode bliver dog hurtigt uoverskueligt.

• Markup baseret UI – Indført i GWT 2.1 med featuren UiBinder – Understøtter overskuelig layout kode – Vil jeg anbefale! Introduktion til GWT Copyright © Lund & Bendsen A/S

28


Hvad er UiBinder ? • Et GWT-modul, som gør det muligt at splitte dit View’s kode i XML markup og Java kode. – XML formidler bedre View’ets struktur og indhold – Programmatisk logik (event kode) bibeholdes i Java Greeter.ui.xml har widget

GreeterViewImpl har widget

event

UiComposite

UiComposite

opslitning

har

event

GreeterViewImpl

Introduktion til GWT Copyright © Lund & Bendsen A/S

29


Greeter .ui.xml og kode Namespace definition ”g” gør det muligt at benytte GWT Widgets fra pakken som elementer.

<?xml version=”1.0” encoding=”UTF-8”?> <!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"> <ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder“ xmlns:g="urn:import:com.google.gwt.user.client.ui"> <g:HTMLPanel> <div> public class Greeter { Hello, <span ui:field="nameSpan" /> @UiField </div> SpanElement nameSpan; <g:Button ui:field="button" >Greet</g:Button> </g:HTMLPanel> @UiField </ui:UiBinder> Button button;

– GWT compileren spytter fejl ud – GWT Designer viser de kendte compile-fejl markereninger

@UiHandler("button") void onClick(ClickEvent e) { nameSpan.setInnerHTML(name); } .... } Introduktion til GWT Copyright © Lund & Bendsen A/S

30


Eksempel

Læg mærke til: • Pakken dk.lundogbendsen.gwt.client.widgets som indeholder vores egne widgets. • De fleste widgets (eks. AddressEdit) arver fra Composite. • Alle high-level paneler er desuden lazy-loadede. • Men nogle (eks. Header) arver fra andre Widget-klasser – hvorfor? Introduktion til GWT Copyright © Lund & Bendsen A/S

31


CSS og ClientBundles • • • • •

Definer CSS style klasser i .css filer (som altid) Definér en eller flere CSS filer per GWT modul Definér et interface per CSS fil Definér et ClientBundle per modul Du får typesikre Java referencer og lignende opførsel i ui.xml filer

.greetings { width: 75px; margin-right: 7px; }

Referencer i ui.xml: <ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder“ xmlns:g="urn:import:com.google.gwt.user.client.ui"> <ui:with field='res' type='com.my.app.widgets.logoname.Resources'> …. <div class=“{res.style.greetings}”>…</div> </ui:UiBinder>

Typestærke referencer i Java:

Introduktion til GWT

button.addStyleName(Resources.BUNDLE.style().greetings());

Copyright © Lund & Bendsen A/S

32


kald til serveren • GWT-RPC – Asynkrone kald af server side metoder. – Kan lede til kode, som er svært at teste.

• gwt-dispatch – Open source framework, som bygger på GWT-RPC – Introducerer et testbart Command pattern.

• RequestFactory – Enabler serverside JPA entities og DAOs på klienten. – Flytter kun ændrede data (og ikke hele entities) – Dårlig doc + meget umodent. Introduktion til GWT Copyright © Lund & Bendsen A/S

33


Overblik over GWT-RPC arkitekturen Client-side Java-til-Javascript

<interface> RemoteService

Server-side Java

eksponerer serverens adresse/URL.

javax.servlet.http.HttpServlet <interface> MyServiceAsync

<interface> ServiceDefTarget - serviceEntryPointAddress

+ void myMethod(ParamType, AsyncCallback<ReturnType>)

<interface> MyService RemoteServiceServlet

+ ReturnType myMethod(ParamType)

MyServiceImpl

MyService Proxy

4. GWT.create(MyService.class)

X = Vores egne klasser/interfaces

+ ReturnType myMethod(ParamType)

GWT stiller nu en proxy til rådighed, der oversætter asynkrone metodekald til HTTP requests til serveren. X = Servlet API

X = GWT API Introduktion til GWT Copyright © Lund & Bendsen A/S

X

= Autogenereret af GWT

34


Test af brugergrænseflader • Et par visdomsord på området... • Overvej følgende citat:

Test through right interface. Don't test business rules through UI. Test UI through UI.

- Robert C. Martin JAOO Opening Keynote, 2007

• Men indtil nu indeholder vores widgets både UI logik, remote kald og evt. business logik Introduktion til GWT Copyright © Lund & Bendsen A/S

35


split widgets i UI og kompleks logic Model View Presenter: <<interface>> Presenter

<<interface>> View <<interface>> Composite

+ cancel() + save(T data) .....

+ setPresenter(Presenter) + setData(T) Kalder (ved bruger events)

ViewImpl View består kun af Widgets, der udgør det visuelle billede. Det har ingen kompliceret logik.

Linket mellem model og view. • Den reagerer på events fra View’ets widgets, e.g. onClick() og eksekverer den komplicerede logik • Den opdaterer View’et med data fra Model Læser og opdaterer

PresenterImpl

Model

Sætter data i viewet Læser og opdaterer

Modellen kan være en domæne- eller applikationsmodel. Den er helt uvidende om View og Presenter.

(Hvis Supervising Controller)

Benyttes i GWT dokumentationen GWT Development with Activities and Places[6] X = Vores egne klasser/interfaces

X = Servlet API

X = GWT API Introduktion til GWT Copyright © Lund & Bendsen A/S

X

= Autogenereret af GWT

36


Fordele/Ulemper • Separation of concerns – Pæn adskillelse af UI og kompleks logik – Lettere at forstå

• Løs kobling => Let at unit teste med mocking – Ikke brug for GWTTestCase/Selenium/etc.

• Lettere konfiguration til forskellige platforme (klassiske browsere, mobil enheder, etc) • UI-layout-delen kan mestendels implementeres i HTML (og HTML5) med UiBinder. Introduktion til GWT Copyright © Lund & Bendsen A/S

37


Skriv helt almindelige unit test • Skriv helt ordinære unit test på den komplicerede logik. • Brug Model View Presenter til at modelere koden testbart. • Undgå GWTTestCase, da den performer dårligt og sløver bygget (hvilket unit test ikke må) • Undgå Selenium/Watir/... test, da de komplicerer unit test, sløver bygget og desuden ikke kan bruges i TDD. Introduktion til GWT Copyright © Lund & Bendsen A/S

38


Manipuler browser historien! • Et af problemerne med Ajax-applikationer er, at browserens history i udgangspunktet udløses af hele side-skift. • Men det tvinges man ikke til af GWT. Herved kan man få problemer – back-knappen virker ikke. – Ikke muligt at bookmarke sider.

• Løs det ved: – History-klassen: low level GWT API – Activities og Places: high level GWT enterprise API Introduktion til GWT Copyright © Lund & Bendsen A/S

39


Brug af History-klassen • En token (tilstand) kan registreres vha. newItem(String) kaldet på History-klassen, eks.: • Dette afstedkommer en mindre ændring i sidens URL:

History.newItem("welcome-page")

mypage.html#welcome-page

History.addValueChangeHandler(new ValueChangeHandler<String>() { public void onValueChange(ValueChangeEvent<String> event) { String token = event.getValue(); // Restore state based on token ValueChangeHandler's, bliver invokeret når } – Der indsættes et nyt token. }); – brugeren trykker "back" eller "forward" Introduktion til GWT Copyright © Lund & Bendsen A/S

40


Hvad er et Place og en Activity? • • • •

• •

Et URL token repræsenterer sidens tilstand, eks. visning af én guitar. => bookmarks + navigation ! Place er en objektorienteret repræsentation af et URL token En Activity er ansvarlig for at præsentere data i et område af browseren, eks shoppingbasket På baggrund af et Place (og derved en URL) kan en eller flere Activities bestemme hvad der vises på skærmen. Der kan vises en Activity per region Der kan være en Activity per side (Som orkestrerer flere widgets) Introduktion til GWT Copyright © Lund & Bendsen A/S

41


Place - hvordan gør man ? <<interface>> Place

ProductDetailsPlace

• • •

Skriv en Place-klasse per URL token / side tilstand. Skriv en PlaceTokenizer klasse per Place klasse En tokenizer konverterer et URL token, e.g. ProductDetailsPlace#34 til en Place-instans, e.g. new ProductDetailsPlace(34), og omvendt.

<<interface>> PlaceTokenizer<T extends Place> + String getToken(T) + T getPlace(String)

Tokenizer

Fortæl GWT om dine places ved at skrive et PlaceHistoryMapper interface. @WithTokenizers({ProductDetailsPlace.Tokenizer.class, AnotherTokenizer.class, … }) public interface AppPlaceHistoryMapper extends PlaceHistoryMapper {} Introduktion til GWT Copyright © Lund & Bendsen A/S

42


Vis én Activity per side <<abstract>> Activity

• Activities stoppes/startes ved Place skift. • ActivityMapper er bindingen mellem et Place og en Activity. Den bruges, når der skiftes tilstand og GWT skal finde en passende Activity

+ start() + onStop() + mayStóp()

MyActivity

Widget

1..* MyActivity <<interface>> ActivityMapper + Activity getToken(Place)

MyActivityMapper Introduktion til GWT Copyright © Lund & Bendsen A/S

43


Vis én Activity per region <<interface>> Presenter

<<interface>> View <<interface>> Composite

+ setPresenter(Presenter) + setData(Student)

+ cancel() + save(Student) .....

<<interface>> Activity + start() + onStop() + mayStóp()

ViewImpl

MyActivity

<<interface>> ActivityMapper + Activity getToken(Place)

LeftActivityMapper Introduktion til GWT Copyright © Lund & Bendsen A/S

RightActivityMapper

44


Brug factories • Flere klasser har brug for at få fingre i EventBus, Views mm • Skriv et antal factories – Øger læsbarheden i koden (man undgår ustyrligt mange parametre) – Øger testbarheden af Presenters – Man kan nemt styre caching, genbrug og instantiering. – Eksempelvis øges performance ved genbrug af view instanser Introduktion til GWT Copyright © Lund & Bendsen A/S

<<interface>> ClientFactory + getEventBus() + getPlaceController() + getStudentView() + getStudentEditView() . ....

ClientFactoryImpl

ClientFactoryMock

45


Eksempel

Læg mærke til: • Hvordan ClientFactoryImpl er konfigureret i kursist.gwt.xml • Hvordan en implementation for ClientFactory interfaces fås i EntryPoint’ets onModuleLoad()-metode

Introduktion til GWT Copyright © Lund & Bendsen A/S

46


Brug factories Gin @Inject public MyPresenter (MyView view, MyServAsync myServ) { this.view = view; …

• Open source framework • Leverer dependency injection til GWT klientkoden • Dependency inject views, GWT API, egne services m.fl. – Øger testbarheden af klientkoden – Man kan nemt styre caching, genbrug og instantiering. – Eksempelvis øges performance ved genbrug af view instanser

• Konsekvenser – Konfiguration flyttes fra Factories og EntryPoint til GinModule – Simple scenarier ser endnu simplere ud – Komplekse scenarier er mere komplekse (se @RightPanel i eks) Introduktion til GWT Copyright © Lund & Bendsen A/S

47


EventBus • EventBus router events fra en producer til alle interesserede event consumere. • Muliggør løs kobling mellem GWT applikationens kodestumper, e.g. En event-producer skal ikke kende til interesserede consumere. Tænk Observer mønster! • Consumere (vores eller GWTs egne moduler) kan registrere handlere på EventBus’en. En handler tager sig af alle de events som er relevante for dem. notify(ProductAddedEvent(){..})

ProductList + addProduct(Product)

EventBus

ShoppingBasket

fire(ProductAddedEvent(){..})

• Pas på med EventBus, Det kan nemt blive for chatty. • Kun events der har med hele app at gøre skal være i bussen Introduktion til GWT Copyright © Lund & Bendsen A/S

48


Eksempel

Læg mærke til: • ModelChangeEvent og ModelChangeEventHandler • Hvordan LogPanel registrerer en ModelChangeEventHandler på EventBus’en • Hvordan EmployeeEdit og AddressEdit begge kalder EventBus.fireEvent(new ModelChangeEvent(...)) • LogPanel kender ikke EmployeeEdit og AddressEdit og omvendt. Introduktion til GWT Copyright © Lund & Bendsen A/S

49


Undgå <table> baserede panels Widget

Composite

Panel

TabPanel

ComplexPanel

HTMLTable

DisclosurePanel

VerticalSplitPanel

SimplePanel

HorisontalSplitPanel

FlowPanel

StackPanel

Grid

FocusPanel

ScrollPanel

HTMLPanel

DeckPanel

FlexTable

PopupPanel

LazyPanel

CellPanel VerticalPanel HorisontalPanel DockPanel

• De er fra før GWT 2.0 DecoratorPanel FormPanel AbsolutePanel • Layout er uforudsigeligt • Virker ikke i standards mode (<!DOCTYPE html>) RootPanel •

Højde og bredde af child widgets respekteres ikke • Forskelle i måden browseren allokerer plads til rækker og kolonner kan lede til uønsket opførsel.

• Indre scroll områder var nærmest umulige at Introduktion til GWT lave uden ekstra kodemængder. 50 Copyright © Lund & Bendsen A/S


Brug de nye Layout panels Widget Composite ResizeComponent

Panel DisclosurePanel SimplePanel

TabLayoutPanel

ComplexPanel

HTMLTable

SimpleLayoutPanel

StackLayoutPanel

ResizeLayoutPanel

FlowPanel

DeckLayoutPanel

Grid

FocusPanel

ScrollPanel

HTMLPanel

AbsolutePanel

FlexTable

PopupPanel

LazyPanel

CellPanel

RootPanel

LayoutPanel

DockLayoutPanel

RootLayoutPanel

SplitLayoutPanel

• Erstat VerticalPanel med FlowPanel FormPanel • Erstat DockPanelDecoratorPanel med DockLayoutPanel • HorizontalPanel er ikke nem, men den erstattes ofte af FlowPanel samt brug af CSS float: left; • Erstat Horizontal- og VerticalSplitPanel med SplitLayoutPanel • Erstat StackPanel med StackLayoutPanel • Erstat TabPanel med TabLayoutPanel Introduktion til GWT • Erstat DeckPanel DeckLayoutPanel 51 Copyright © Lund & Bendsenmed A/S


GWT.UncaughtExceptionHandler • Fejlhåndtering på klienten: GWT.setUncaughtExceptionHandler(new MyHandler());

• Bør dog kun benyttes som sidste udvej, da exceptions bør håndteres hvor de opstår og hvor brugeren kan få mere meningsfuld feedback.

Introduktion til GWT Copyright © Lund & Bendsen A/S

52


Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.