Komponentbaserte webrammeverk: Tapestry 5

Nytt prosjekt, nye muligheter!

Når man planlegger et utviklingsprosjekt for web vil dette som oftest innebære et valg av webrammeverk. Det er etterhvert blitt svært mange å velge blant, og det kan være en utfordring å få oversikt over hva som skiller de ulike rammeverkene. Tradisjonelle action-baserte webrammeverk som Struts2 og Spring MVC har modne og velprøvde API, og blir ofte valgt fordi man her har erfaring fra før og fordi rammeverkene støttes av en stor community. Men blant alternativene som bør vurderes finnes en rekke komponent-baserte rammeverk med en mer høynivå tilnærming. Disse rammeverkene lover rask og effektiv utvikling med et minimum av konfigurasjon, og konfigurerbare, kraftige komponenter som holder på sin egen tilstand og gir rik funksjonalitet rett ut av boksen. Rammeverkene er ment å være utviklervennlige, med utstrakt implementasjon av best pactices.

Tapestry er et open source komponent-basert webrammeverk som har vært under utvikling siden starten av 2000-tallet. Med versjon 5 har rammeverket fått mye oppmerksomhet og positiv omtale. I likhet med Wicket er det nå tatt inn som et Apache-prosjekt, noe som betyr at kildekoden er tilgjengelig med Apache Software Licence 2.0.

Hvorfor skal så du vurdere dette rammeverket kontra tradisjonelle action-baserte webrammeverk?

Utviklerne bak Tapestry har definert fire egenskaper som de anser som de viktigste for et rammeverk:

  • Enkelhet – å utvikle webapplikasjoner skal ikke trenge å være så komplisert. Mye kompleksitet blir håndtert av rammeverket, som utvikler skal du få fokusere på forretningslogikk.
  • Konsistens – Rammeverket skal ha en konsistent oppførsel, med komponenter som er “self contained”, altså holder på sin egen tilstand. Webapplikasjoner lagd med Tapestry skal ha en uniform struktur og utviklere skal kunne bygge på best practices.
  • Effektivitet – Applikasjoner basert på Tapestry skal ha god ytelse og skalerbarhet. Utviklingsprosessen skal også være så effektiv som mulig.
  • Tilbakemelding – Rammeverket skal gi god og relevant informasjon til utvikler hvis feilsituasjoner oppstår.

Hvordan er så dette implementert i Tapestry 5?

Enkelhet

En webapp lagd i Tapestry består av et sett med sider som håndteres av rammeverket. En side består av en template (med en eller flere gjenbrukbare komponenter) og en tilhørende javaklasse med samme navn. Javaklassen er en POJO uten avhengigheter til andre deler av rammeverket; ingen superklasse som må extendes, ingen interface må implementeres.

Denne understøttende javaklassen tilsvarer en Controller i et action-basert rammeverk, og håndterer events som kommer fra viewet. Dette ligner mye på måten tradisjonelle desktop-applikasjoner fungerer, og innebærer et høyere nivå av abstraksjon fra request/response-modellen som f.eks Struts2 og Spring MVC bruker. Urler og request-parametere er erstattet av metoder og egenskaper ved side-objekter. Komponenter er også bygget opp på samme måte; en template og en javaklasse med samme navn, uten avhengigheter. Bruken av POJOs gjør det lett å lage egne testbare komponenter, samt å utvide eksisterende komponenter.

Så hvordan kan Tapestry sette sammen templates og tilhørende javaklasser når disse ikke arver fra en rammeverkspesifikk superklasse eller implementerer bestemte interfaces? Tapestry bruker bytecode weaving til å legge til tapestryspesifikk kode ved runtime. Dette skjer ved at sider og komponenter bruker annotations for å beskrive hvordan rammeverket skal håndtere koden. En kan også bruke navnekonvensjon på metoder som lytter på events, og dermed redusere bruken av annotations. Den utstrakte bruken av annotations og navnekonvensjoner øker lesbarheten og reduserer mengden boilerplate kode.

En siste viktig detalj mht enkelhet er at konfigurasjon gjøres programatisk i en egen javaklasse. Dette gir svært lite deklarasjon i XML å forholde seg til, kun web.xml. Tapestry kommer med en defaultkonfigurasjon som man kan utvide og endre ved behov.

Konsistens

Et viktig designprinsipp for Tapestry er “convention over configuration”. Sider, komponenter, templates, services etc må ligge i bestemte kataloger, og følge bestemte navnekonvensjoner. Det man tjener på dette er redusert behov for konfigurasjon, samt en konsistent struktur på webapplikasjonen.

Alle komponenter er self-contained og kan plasseres på hvilken som helst side. De holder sin egen state uten behov for parametere.

Effektivitet

I likhet med andre komponentbaserte webrammeverk er Tapestry svært velegnet til prototyping og rask utvikling av webapplikasjoner.

Kraftige, gjenbrukbare komponenter gir mye funksjonalitet ut av boksen, og disse er enkle å modifisere og utvide. Det er også enkelt å utvikle egne komponenter. Rammeverket kommer med bl.a URL-håndtering, mulighet for tilstandshåndtering på klient eller server, inputvalidering, internationalization, AJAX-støtte og feilrapportering innebygget, og integrasjon mot en rekke kjente rammeverk som Spring og Hibernate er inkludert.

Som utvikler ønsker man å produsere mest mulig funksjonalitet raskest mulig, med færrest mulig feil. Code-test-deploy roundtrip bør derfor være så kort som mulig, og rammeverket må understøtte testdrevet utvikling. Nettopp effektivitet og testbarhet er blant Tapestrys sterkeste kort.

Med live class reloading av alle komponent-klasser trenger man ikke redeploye aplikasjonen for å se resultatet av en endring i koden. Tapestry har en egen classloader som ser etter endringer i koden, og dette muliggjør høy produktivitet. Ettersom komponentene i Tapestry håndterer sin egen tilstand og eventhandling abstraherer bort mye kompleksitet kan utviklere heller konsentrere seg om forretningslogikk. Tapestry er også velegnet for TDD, med sider og komponenter som er POJOs uten avhengigheter til rammeverket.

Et annet viktig prinsipp for Tapestry er “static structure, dynamic behavior”.
Med dette menes at strukturen til en gitt side er statisk mens logikken i komponentene gjør at sidene likevel er dynamiske. Med en statisk instans av strukturen for en side kan denne pooles av rammeverket. Dette gjør at en side som aksesseres flere ganger vil gjenbrukes, noe som er gunstig både for ytelse og skalering. Tapestry lagrer mindre data i HttpSession enn andre komponentbaserte rammeverk som JSF og Wicket, fordi bare data fra en side lagres, ikke hele side-instansen.

Tilbakemelding

Når en feilsituasjon oppstår vil Tapestry gi utvikler en detaljert og informativ feilmelding. Feilmeldingen vil referere til riktig kodelinje i den originale kildekoden, med et utsnitt av den aktuelle kodebiten og en mulig feilårsak og løsning.

Så er alt bare gull og Tapestry 5 et soleklart valg i ditt neste prosjekt?

Det er endel aspekter man bør være klar over når man vurderer Tapestry.

Rammeverket har fått endel pepper for manglende bakoverkompatibilitet ved major releases. Versjon 5 er en omfattende omskrivning ift v4, og en migrering av et eldre prosjekt vil være tidkrevende. Nå loves det fra utviklerne at man f.o.m v5 ikke skal få dette problemet så lenge selve grunnkonseptene ikke endres.

Komponenter som håndterer sin egen tilstand gjør at man kan få mye data i session scope og dermed stort minneforbruk; dette er en generell problemstilling for komponentbaserte webrammeverk. Tapestry håndterer dette vha førnevnte side-pooling og lagring kun av data for en side i session. Man kan også optimalisere applikasjonen ved å sette en grense for antall sider i session.

Bruken av en pool med side-instanser begrenser også den potensielt uheldige effekten for ytelse som runtime bytecode weaving kan ha. Sider vil ta kun ta lenger tid å laste ved førstegangs aksess, så dette er ikke et større problem i Tapestry enn f.eks i JSP.

Feilsøking i generert tapestrykode kan være frustrerende. Koden du har skrevet blir vevd sammen med tapestrykode runtime, og en bug kan ligge i koden fra rammeverket. Du har da muligheten til å sette loglevel til DEBUG, og få ut logg for den endelige, genererte koden.

Lærekurven kan være bratt hvis man tidligere kun har skrevet webapplikasjoner i action-baserte rammeverk. Erfaring fra utvikling av desktop-applikasjoner vil være relevant for det programmeringsparadigmet man bruker i Tapestry. Dokumentasjonen er blitt mye bedre med versjon 5, og veien til den første Hello World-applikasjonen er ikke lang.

Tapestry har færre brukere og aktive commiters enn f.eks Struts2, Spring MVC og JSF, men community er i vekst nå som Tapestry er blitt et Apacheprosjekt.

Konklusjon

Hvis du skal vurdere webrammeverk til en applikasjon med et rikt GUI og ønsker å utvikle dette uten bruk av plugins må komponentbaserte webrammeverk vurderes. Med Apache i ryggen og en økende brukermasse er Tapestry 5 et webrammeverk i positiv utvikling.

Tapestry gir deg et bibliotek med kraftige, utvidbare og godt dokumenterte komponenter, og sikrer en rask utviklingssyklus med live class reloading. Rammeverket forenkler utvikling av rike GUI for web og er godt egnet for testdrevet utvikling. For å oppnå enkelhet ved utvikling må man ofre noe fleksibilitet. Ved å akseptere de valg som er gjort i rammeverket får man konsistens, på bekostning av ubegrenset mulighet til å implementere egne patterns.

Tapestry 5 bør være på lista når webrammeverk skal velges i ditt neste prosjekt.