Den här websidan ser mycket bättre ut i en bläddrare som följer rådande webstandard, men du kan titta på sidan med andra bläddrare också.

Bluefish :: Akvariet

Bluefish logo
Logo

Java Server Faces

Java Server Faces och enhetstester

Java Server Faces och Hibernate

Hibernate och JBoss

Lunar Linux and Zepto 4200

Att delta i projekt med öppen källkod

Java-projekten i Apache

Hibernate - en introduktion

HemsideByggaren under huven

Öppen källkod på Bluefish

JavaOne 2003

Lime

OOPSLA 2002

AOP

fixafest.nu under huven

Linux From Scratch

Bluefish skänker

XSL

JDepper

OOPSLA 1999

Teknisk beskrivning av fixafest.nu

Publicerad 2002-07-22

Den här artikeln beskriver hur Bluefish gratis-webbtjänst fixafest.nu ser ut "under huven". Mer övergripande information om tjänsten hittar du på vår beskrivning av plantan fixafest.nu, och förstås på tjänstens egna sida.

Teknisk historik

Version 0...

Ursprunget till fixafest.nu var en liten webbtjänst för att hantera inbjudningar till en specifik fest, nämligen Robert Buréns 30-årskalas. Tanken var inte då att det skulle användas igen senare, så det var verkligen ett "snabbt hack". En ren JSP-lösning användes, med en inte helt snygg blandning av Java-kod och html i JSP-filerna. Som underliggande databas användes Microsoft Access, vid en JDBC-ODBC-brygga. Inte snyggt, men det löste uppgiften!

Version 1

Den första versionen av fixafest.nu byggde vidare på kalastjänsten med att lägga till möjligheten för andra att registrera sig och hantera sina egna fester. Vi migrerade till att använda MySQL istället för Microsoft Access, och försökte bryta ut så mycket som möjligt av funktionaliteten i Java-bönor som anropades från JSP-sidorna, men i övrigt var det tydligt att detta bara var en utökad version av det ursprungliga hacket.

Version 2

Till nästa version passade vi på att göra refactoring och se till att vi fick en arkitektur som faktiskt skulle kunna klara av att lägga till nya funktioner på ett säkert sätt. Vi började också använda bättre verktyg för byggande av webbtjänster, som Struts, Ant och JUnit. Vi började bygga bort all Java-kod från JSP-sidorna, och skapade istället egna JSP-taggar för presentationslagret. Dessutom passade vi på att göra om utseendet på hela webbtjänsten till något som liknar det som finns idag.

Fixafest version 3

Något om J2EE

Java 2 Enterprise Edition J2EE är en samling specifikationer kring olika serverrelaterade tekniker. Dessa tekniker bildar tillsammans i ”implementerad form” en J2EE kompatibel applikationsserver. Exempel på ingående tekniker kan vara JSP (Java Server Pages), Servlets eller EJB (Enterprise Java Beans). De olika ingående teknikerna tillhandahåller vad man brukar kalla en kontainer i vilken en applikationsutvecklare kan placera sina applikationskomponenter. J2SE (Java 2 Standard Edition) version 1.3 eller senare är ingångskrav på den bottenplatta som senaste versionen av J2EE står på. Det trevliga är att J2EE applikationsservern tar and om saker som är krångligt och överlåter applikationsutvecklingen till oss.

J2EE

J2EE har idag blivit den ledande plattformen för serverrelaterade applikationer. Det finns idag flertalet J2EE-kompatibla applikationsservrar på marknaden som tävlar om att bli bäst vilket i sin tur driver nästkommande version av specifikationen. Eftersom flera olika applikationsservrar stödjer J2EE är det fullt möjligt att flytta sina applikationskomponenter från en J2EE-server till en annan. Självklart innebär det ett praktiskt jobb med de olika servrarnas egenheter men det ger oss flexibla möjligheter och vi sitter inte fast med en applikationsserver om något problem uppstår. Dessutom är vi som konsulter snabbt med på banan med olika applikationsservrar eftersom J2EE-koncepten går igen. När vi byggde Fixafest version 3 valde vi opensource-alternativet Jboss i kombination med Tomcat som J2EE-applikationsserver. Förutom att genom JSP/Servlet teknik tillhandahålla en webbklient är det dessutom möjligt att bygga fullskaliga javaapplikationsklienter eller applet/javawebstart-lösningar.

Arkitektur

Fixafest är byggt kring J2EE med ett webblager uppstyrt genom Jakarta-Struts-ramverket, ett ”affärsskikt” med EJB-komponenter och längst bak en databashanterare för att lagra festinformation. Då Jboss 3 var i tidigt betastadium under Fixafests utveckling valdes BMP (Bean Managed Persistence) som persistensmodell för applikationen. Enkelt förklarat innebär det att vi själva fick skriva den SQL-relaterade koden i våra entitetsbönor istället för att EJB-kontainern hanterar databas accessen via CMP-modellen (Container Managed Persistence). Tomcat, Jboss och MySQL snurrar allihopa på samma Linux (Debian) server. Detta funkar om lasten inte är så stor. Ifall Fixafestanvändandet stiger mycket så kan det vara lämpligt att t.ex. låta en dedikerad maskin sköta databashanteringen, dvs flytta MySQL till sin egen server.

Arkitektur

Mail-utskickning från systemet köas upp via en JMS-kö för att frigöra applikationsservern från allt för långa requests. Webblagret använder förutom Struts en hel del egentillverkade JSP-taggar för att slippa använda scriptlets i JSPsidorna.

JBoss

JBoss är en opensource implementation av J2EE. JBoss är fokuserat kring EJB delen av J2EE och lämnar webblagret till andra att implementera. Det går att ladda ner JBoss bundlad och klar tillsammans med Tomcat 4 samt Jetty (en alternativ webbkontainer). JBoss 3 stödjer senaste EJB specifikationen (2.0) med allt vad det innebär samt har en intressant JMX baserad ”microkernel-arkitektur” genom vilken klustring lär vara en enkel match att få snurr på. JBoss ligger allt som oftast i top på Sourceforge som ett av dom allra mest produktiva opensource-projekten och har i och med version 3 blivit en J2EE applikationsserver att räkna med. JBoss kommer med all säkerhet ge dom stora kommersiella applikationsservrarna en match om J2EE-marknaden. I dagsläget haltar tyvärr dokumentationen en del men under höstens inledning kommer även den att vara med på banan med en del böcker som publiceras m.m.

JBoss i Fixafest

Vi har implementerat vår ”affärslogik” som EJB-komponenter som exekveras av JBoss. Vi använde BMP Entitybeans (Bean Managed Persistence) för att hantera persistens. Ambitionen var att använda CMP men då vi använde en tidig beta av JBoss 3 valde vi att själva ha koll på det hela genom BMP. Förutom entitetsbönor så har vi ett ”fasadlager” med tillståndslösa sessionsbönor i vilka själva logiken ligger. Vi utnyttjar dessutom JMS (Java Message Service) som intern kö då Fixafest ska skicka festrelaterade mail för att det hela ska flyta på smidigt.

Tomcat

Fixafest använder Tomcat 4.0.x som JSP/Servlet kontainer dvs den främre delen av den J2EE kontainer i vilken Fixafest huserar ofta kallat ”webblagret”. Tomcat 4 är så kallad referensimplementation för Servlet specifikation version 2.3 respektive JSP Specifikation version 1.2 som båda ingår i J2EE version 1.3. Tomcat är en lämplig produkt att börja med då den är relativt enkel att konfigurera och vill man experimentera med Jakarta-Struts så behöver man en JSP/Servlet kontainer. Senaste version av Tomcat är i dagsläget 4.0.4 men en upphottad generation 4.1.x är på väg med en helt omskriven JSP-del som åtgärdar prestandaproblem samt inkluderar en administrationsapplikation (För att administrera Tomcat). Tomcat 4.1.x är dessutom på samma sätt som JBoss konfigurerbar via JMX. En liten detalj kring administrationsapplikationen är att den använder Jakarta-Struts som ”bottenplatta” och för den nyfikne är det förstås bara att kika i dess kod. För att integrera smidigt med webbservern Apache finns en speciell plugin.

Struts

Jakarta-Struts är ett ramverk kring JSP/Servlet teknikerna som tillhandahåller en så kallad Model View Controller (MVC) implementation. Väldigt enkelt skulle man kunna säga att Struts inför ordning och reda i webblagret som utan styrning kan bli en rörig historia. Använder man inte Struts till sin applikation är sannolikheten stor att man börjar bygga något liknande. Det kan vara en liten tröskel att lära sig Struts men ska man bygga en webbapplikation med JSP/Servletteknik rekommenderas Struts som ”bottenplatta”.

Struts

Struts består i praktiken av en så kallad controllerservlet (ActionServlet) och ett antal taglibraries.

ActionServlet

En Strutsapplikation konfigureras via en XML-fil (struts-config.xml) som definierar de olika Action’s som applikationen kan anropa. Dessutom anger man i denna fil logiska namn på de JSP sidor som används för rendering av de olika vyerna applikationen tillhandahåller. På detta sätt kommer man runt hårdkodning av navigeringsflöden i applikationen och låter struts ActionServlet kontrollera flödet. ActionForm klasser definieras dessutom här som mottagare av htmlformulärsinformation.

Struts taglibs

Struts tillhandahåller en riklig arsenal med användbara taglibraries som förenklar modellåtkomst vid rendering. Dessutom finns användbara taggar för att hantera logiska operationer samt diverse andra taggar av htmlteknisk karaktär.

Struts i Fixafest

En viktig detalj när man använder Struts är centralisera inkommande requests. Genom att alltid passera Struts actionservlet är detta möjligt. Detta åstadkommer man genom att alltid låta applikationen navigera via actions, dvs genom Struts actionservlet som delegerar till ansvarig action-klass. I klartext innebär detta att samtliga länkar i applikationen har URL’er som avslutas med .do t.ex. festinfo.do. Inga direktlänkar till någon .jsp sida bör förekomma eftersom man då tappar kontrollen. Förutom att alltid navigera via Struts-actions så bör man i applikationen införa en central punkt vilken användare alltid passerar. Detta kan man göra på flera sätt där vi till Fixafest valde att införa en basklass för våra actions från vilken alla våra actionimplementationer ärver. Med en central ingång får man möjlighet att kontrollera användarens navigering t.ex. att användaren har behörighet att exekvera aktuell action. En annan variant är att tillhandahålla en egen ActionServlet ärvd från Struts actionservlet. Kommande Struts version 1.1 tillhandahåller en mer dynamisk funktion för att ”plugga in” egen basfunktionalitet. Struts 1.1 finns redan idag som beta men bör vara klar tidigt under hösten.

Verktyg

Ant

Ant är ett javabaserat byggstöd. Man skulle kunna beskriva Ant som make byggt i java. Istället för en makefil används en eller flera build.xml filer som beskriver vad som ska ske. I build.xml anger man olika ”tasks” och beroenden liknande make. Det trevliga med ant är att det är specialdesignat för javapplikationsutveckling och vanligtvis krångliga handgrepp finns färdigt som tasks t.ex. För att kompilera en filstruktur rekursivt från ${src} till ${build}:

Ant

Förutom grundläggande tasks finns flertalet avancerade tasks som t.ex. att kommunicera med versionshanteringssystem, generera javadocm skicka filer med ftp, exekvera enhetstester (JUnit) m.m. Dessutom kan man enkelt tillverka sina egna tasks där ant inte räcker till. En annan viktig poäng kontra make är att make inte normalt är användbart på Windowsburkar. Genom att använda ant kan utvecklarna bygga systemet på samma sätt oberoende om det är en Windowsburk eller någon Linuxmaskin. Ant är en klockren komponent helt enkelt.

Ant i Fixafest

Fixafest använder ant till följande:

  • Kompilera
  • Paketera applikationen (bygga ear- och war-filer)
  • Deploya EJB-komponenter i JBoss
  • Exekvera enhetstester (JUnit)
  • Generera Javadoc
  • Starta / Stoppa JBoss och Tomcat
  • EJB Spec. verifiering (Suns verifier tool)
  • Uppstädning

JUnit

JUnit är ett ramverk för att bygga enhetstester för javaklasser och komponenter. Testfall, vilka ärver klassen TestCase, kör ett givet antal tester mot en komponent varefter resultatet av testerna rapporteras i konsolen. Via reflection letar JUnit reda på alla metoder som börjar med 'test' i din klass och exekverar dem. För att vara säker på att resultatet av ett test är det förväntade, finns ett antal hjälpmetoder som man bör använda flitigt i sina testfall. De heter alla något med assert, t ex assertTrue(boolean b). I din testfallsklass anropas metoder i din Java-komponent och därefter anropas lämpliga assert-metoder för att verifiera resultaten.

Exempel:

public void testGetPartyDetails() throws Exception{
  Utils.getLogger().info("*** Entering testGetDetails ***");
  User user = getUser("frodo");
  assertNotNull(user);

  Collection coll = user.getParties();
  ServerUtils.getLogger().info("*** Got " + coll.size() + " parties ***");
  assertEquals(1, coll.size());

  Party party = (Party)coll.iterator().next();
  PartyDetails details = party.getDetails();

  assertNotNull(details);

  Utils.getLogger().info(details);
}

I metoden ovan hämtas en användare ('frodo') och han förväntas i detta test ha en fest, varefter detaljinformation om denna fest hämtas. För att förbereda ett enhetstest erbjuder JUnit tjänsterna setUp och tearDown vilka exekveras innan respektive efter testmetoderna körs. Genom att implementera dessa tjänster i enhetstestsklassen kan man t ex allokera nödvändiga resurser eller lägga upp data som enhetstestet behöver. I fallet ovan skulle typiskt användaren 'frodo' skapas och få en fest definierad.

Enhetstester kan skapas på olika nivåer. I vissa fall kan det vara vettigt att börja utvecklingen av en komponent med att skriva de enhetstestklasser som skall testa komponenten. I fixafest.nu skrev vi enhetstesterna på ganska hög nivå så att de närmast kan liknas vid användningsfall - t ex:

  • Skapa en användare
  • Lägg upp en fest
  • Lägg till personer i adressboken
  • Lägg till inbjudningar

Efter ett tag fick vi ett gäng enhetstester som vi körde lite då och då under utvecklingen. En klar fördel med detta är att man får väldigt bra stöd då man vill göra lite mer genomgripande förändringar i koden; man gör sina förändringar och kör sedan hela sviten av enhetstester. Om dessa då går igenom utan att knorra så har man i alla fall inte gjort något grundläggande fel.

/Mikael Printz, Torben Norling, Robert Burén och Ali Abida

Bluefish logo

Bluefish AB :: Sturegatan 34 :: 114 36 Stockholm :: tel 08 459 93 30 :: fax 08 459 93 39 :: e-post info@bluefish.se