Olle Hallin

Olle Hallin

Om systemutveckling i största allmänhet

Mitt drömuppdrag

Som frilansande konsult kan man ju oftast inte utforma sina egna uppdrag, utan man får ta det som kommer i ens väg.

Har man tur kan man välja mellan två eller kanske till och med tre olika uppdrag. Har man haft bra beläggning under en tid och lyckats samla i ladorna kan man stå över tills det kommer något bättre i ens väg. Men till slut har man inget val alls utan måste ta vilket uppdrag som helst eftersom skattmas och bolåneinstitut skall ha sitt.

Nu är det inte så illa för mig, men jag tar mig i alla fall friheten att utforma mitt drömuppdrag. Om många vet vad jag drömmer om är ju chansen att det slår in större, eller hur?

read more »

Hur man låter Gradle kolla om man har de senaste versionerna av sina tredjepartsbibliotek

Inledning

Nu för tiden använder nog de flesta Javaprojekt någon sorts dependencyhanterare i sina byggen.

Den tid då man checkade in sina tredjepartsbibliotek i versionshanteringen är förbi. Nu låter man Maven (eller Ivy eller Gradle) läsa en incheckad förteckning, hämta hem jarfilerna ifrån de centrala förråd som finns därute och sätta upp class path.

En sak som dessa verktyg dock inte hjälper till med är att hålla koll på att man inte ligger kvar på gamla versioner. Att köra på gamla versioner kan ses som en sorts teknisk skuld, eftersom det blir värre och värre att uppgradera ju fler versioner man har missat.

Det är dock ett mödosamt och tråkigt manuellt arbete att kolla hur bra man ligger till.

Jag har därför utvecklat en Gradle-task som automatiserar detta!

(Se där, ännu en anledning att byta till Gradle!)

read more »

Hur man kan hantera Continuous Delivery med MongoDB

MongoDB är en schemalös, dokumentorienterad databas som har fått stor popularitet i den agila världen bland annat därför att man inte behöver underhålla något databasschema.

MongoDBs schemalöshet gör att många leds att tro att Continuous Delivery blir en promenad i parken, eftersom det ju inte behövs några datamigreringar när man driftsätter en ny version av koden!

Rent teoretiskt är detta sant, men är ett sluttande plan in i Land of Crappy Code™ !

För att slippa onödig komplexitet i form av varierande utseende på lagrade domänobjekt beroende på deras ålder, rekommenderar jag att man utför regelrätta datamigreringar även när man använder MongoDB!

Jag rekommenderar även att datamigreringen är en del av applikationen — till skillnad från skript som skall köras vid sidan av innan applikationsstart — helt enkelt för att eliminera risken för misstag.

Jag har i mitt sidoprojekt Varmfront.nu utvecklat en kompakt liten lösning som i MongoDB implementerar det som Flyway gör för SQL.

Mönstret bygger på Spring Data for MongoDB och Spring JavaConfig, och migreringarna är skrivna i Java. That’s right folks, no XML here :D

Läs vidare, så får du se hur man kan göra!

read more »

Äventyr i molnet – del 4

Jag ber om ursäkt för det långa uppehållet sedan förra delen. Förklaringen stavas Valle. Valle är en hund, närmare bestämt en Lagotto Romagnolo. Valle är nu snart ett år gammal, så nu har jag “fritid” igen. Wohoo!

Denna gång skall det handla om något som så gott som alla webappar behöver, nämligen användarhantering och autenticering.

Handen på hjärtat, visst vore det skönt att kunna plugga in en färdig användarhantering, och kunna låta folk logga in med sina redan existerande Facebook/Google/Windows Live/Twitter/whatever-konton?

Om svaret är ja, läs vidare!

OpenID

Det finns en standard för tredjepartsautenticering som heter OpenID, som så gott som alla stora sociala nätverk stödjer.

Problemet med OpenID är att det är ganska pilligt att få på plats, och det är inte helt uppebart för en användare hur han skall logga in med sitt OpenID.

Ett annat problem är att alla sociala nätverk har olika API:er för att hämta användardatat, efter att själva autenticeringen är klar.

Du måste dessutom bygga själva logindialogen själv. Detta är inte speciellt svårt, men ändock ett jobb.

Här kommer Janrain till din räddning!

Janrain

Janrain är en mäklare för tredjepartsautenticering.

De säger själva att de erbjuder användarhantering som en Software-as-a-Service (SaaS).

Janrain erbjuder ett uniformt API för att accessa de olika sociala nätverk som de stödjer. Det är dock vissa skillnader på vilka data om en användare som de olika nätverken lämnar ut. Till exempel så lämnar LinkedIn inte ut epostadresser, vilket åtminstone Google, Facebook och Windows Live gör.

Med Janrain är det lätt att lägga till användarhantering. Det går i princip till så här:

  1. Registrera din app på janrain.com. Du kan logga in med vilket som helst av dina sociala konton (Janrain äter sin egen hundmat!)
  2. Ange vilka sociala nätverk du vill använda för autenticering.
  3. Kör en wizard på Janrain som genererar en snutt Javascript som du kopierar in till din webbsida, omedelbart före .
  4. Wizarden genererar också en kodsnutt för HTML-länken Logga in…
  5. Implementera en callbackrutin som anropas av Janrain när en användare har autenticerat sig. URL:en till denna callbackrutin bestämmer du själv, och du anger den i wizarden i steg 3.
  6. Callbackrutinen anropas av Janrain med en HTTP POST som har en enda parameter, token. Denna token använder du tillsammans med den applikationsidentitet som du fick i steg 1 för att anropa ett Janrain API för att hämta användarinfon. API:et är en vanlig HTTP POST, som returnerar användardatat antingen i XML- eller JSON-format.

Klart!

Nu har du en komplett användarhantering, och dina användare kan direkt logga in och börja använda din sajt.

Klick på loginlänken öppnar en dialogbox som automatgenereras av Janrain-scriptet. I denna dialog kan användaren välja vilket nätverk han vill logga in på din sajt med.

I användardatat du får tillbaka från Janrain ingår en globalt unik OpenID-identitet. Denna kan du använda som nyckel för de applikationsspecifika användardata du vill spara i din egen databas. Du behöver inte lagra själva användardatat (namn, epostadress och så), för det får du ju serverat på nytt varje gång någon loggar in till din sajt.

Vill du stödja ett nätverk till? Logga in på janrain.com och ändra i kontrollpanelen för din app. (I många fall måste du dessutom registrera din Janrain-app hos nätverket i fråga.)

På janrain.com har din app en egen kontrollpanel där du kan se statistik på inloggningarna. Troligen inte det första du skulle bygga om du byggde användarhanteringen själv.

Funktioner för registering, glömt lösenord med mera finns ju redan på de olika sociala nätverken, så det slipper du också bygga.

Så sammantaget får du en komplett användarhantering på några timmar!

Så vad kostar det?

Det här låter för bra för att vara sant, det måste finnas en hake. Det kostar säkert skjortan?

Janrain kör med principen första silen gratis, dvs det är kostnadsfritt upp till 2500 unika användare och 6 st sociala nätverk.

För 100 USD/år kan du ha 5000 unika användare, och 12 sociala nätverk. Då får du dessutom tillgång till mer användardata än i gratisvarianten.

Räcker inte detta finns ytterligare en variant, men prislappen på denna är inte publicerad.

(Om det går så bra så att du får fler än 5000 unika användare är det bara att gratulera! Du har säkert råd med nästa nivå…)

Mönster för flertrådade enhetstester

Detta är ett designmönster för hur man skriver ett enhetstest som utför samma test samtidigt i flera trådar.

Genom att utnyttja java.util.concurrent på ett smart sätt säkerställer man maximal samtidighet, vilken kan avslöja trådbuggar.

Kom ihåg: det går inte att bevisa att ett program är fritt från trådbuggar. Det handlar om att göra det sannolikt att det fungerar i en flertrådad miljö.

Kodmall



    @Test
    public void testSomething() {
        assertTrue(true);
    }

    @Test
    public void testConcurrentAuthInfoResponse() throws InterruptedException {
        final int threads = 100;

        final CountDownLatch readyToStart = new CountDownLatch(threads);
        final CountDownLatch startingGun = new CountDownLatch(1);
        final CountDownLatch finishLine = new CountDownLatch(threads);
        final AtomicInteger failCount = new AtomicInteger();

        for (int i=0; i

Visserligen en hel del boilerplate, men det kan man faktorera ut till en Template á là Springs JdbcTemplate.

Äventyr i molnet – del 3

Inledning

Nu när det finns en första "Hello, World"-version av Eats-o-matic i drift, är det dags att fundera på allvar på den vidare utvecklingen.

För att det skall bli något så behövs det bland annat möjlighet att lagra data, samt ett ramverk för att skapa själva webbapplikationen med.

Jag har kollat igenom ett antal av de alternativ som finns för GAE och kommit fram till ett val som jag tror passar mig som utvecklare och Eats-o-matic som applikation.

Persistens

Vi tar det enkla beslutet först, val av persistensmekanism.

GAE erbjuder två programmeringsgränssnitt för att lagra data: Java Data Objects (JDO ) och Java Persistence Architecture (JPA). (Egentligen finns det ett tredje, lågnivågränssnittet mot Googles egna Big Tables. Men detta tänker jag inte ens beakta, för då har man låst sig hårt mot GAE:s driftsmiljö, vilket bär mig emot.)

JDO är en ganska gammal och beprövad standard, medan JPA är tämligen färskt. Varför JDO inte har fått större spridning förstår jag faktiskt inte. Det passar utmärkt för en stor mängd av tillämpningar. Det är heller ingen brist på effektiva, billiga och stabila implementationer.

(Vissa elaka tungor i blogosfären säger att Sun tog fram JPA efter starka påtryckningar från de ledande RDBMS-leverantörerna, vars produkter inte fungerar så bra med JDO.)

JDO togs ursprungligen fram som ett standard-API för att lagra data i stort sett vilket medium som helst, medan JPA mer eller mindre förutsätter att datat skall lagras i en relationsdatabas.

I GAE så hamnar datat i bägge fallen i BigTable, som varken är en objektdatabas eller en relationsdatabas.

I GAE så används i bägge fallen DataNucleus som verktyg för att vid byggtillfället modifiera dina persistenta klasser så att de går att lagra. Så valet mellan JDO och JPA avgörs av vilket API som passar applikationen bäst.

Jag har jobbat en del med JPA och Hibernate och MySQL, vilket inte var helt friktionsfritt. Det märks att objekt inte är rader i en tabell, utom i det mest triviala fallet. (Jag har lusläst Hibernatedokumentationen flera gånger, och är fortfarande inte säker på att jag förstår allt som står där…)

Jag har även jobbat med db4o, vilket var betydligt mer rättframt. db4o och JDO har väldigt lika programmeringsmodeller.

Så jag satsar mina pengar på JDO.

Kombon JDO + DataNucleus är speciellt tilltalande, eftersom DataNucleus kan använda i stort sett vad som helst för att persistera JDO-objekt; db4o, SQL-databaser, XML-filer, Excel-filer och så vidare.

Detta betyder att jag kommer att kunna enhetstesta min persistenskod mot en lokal db4o-fil, utan att behöva dra igång vare sig en separat db4o-server eller GAE:s integrationtestmiljö. Detta betyder tidsbesparingar!

Som sagt, persistensen överlåter jag med varm hand åt JDO.

Webbramverk

Här är valet betydligt svårare.

Jag är en gammal anhängare av Tapestry, som är ett komponentorienterat ramverk i samma skola som t.ex. Wicket och JSF. Jag har jobbat med Tapestry mer eller mindre kontinuerligt sedan 2003 fram till den dag som idag är.

Tyvärr fungerar inte senaste versionen av Tapestry (5.1) i GAE på grund av Tapestry använder en XML-parser som inte finns med på GAE:s white list.

Wicket lär också ha en del problem i GAE. Jag har bara hört det ryktesvägen och vet inte exakt vad de består i och om de oöverstigliga. Men eftersom jag inte kan Wicket så vill jag inte både lära mig Wicket och ta strulet med att få det att funka i GAE.

JSF har jag stött på i ett projekt, och lärt mig att avsky. Maken till krångligt ramverk får man leta efter. (JSF 2 lär vara bättre, men det har jag inte provat. Jag är inte heller lockad att prova.)

Sedan finns det c:a 100 stycken MVC-ramverk; Spring MVC, Struts, Struts 2 osv. Men har man en gång jobbat med ett komponentramverk så vill man inte tillbaka. Det känns helt enkelt inte bra.

Så mitt val är egentligen ett blindval: jag väljer ett ramverk som garanterat fungerar i GAE och som är komponentorienterat, men som jag aldrig har jobbat med: Google Web Toolkit (GWT).

Att GWT fungerar i GAE tar jag för givet, eftersom bägge är skapade av Google.

Jag har kollegor på Crisp som brukar hylla GWT, och jag litar på dem. Dessutom har jag därmed support på nära håll!

Jag tror även att GWT kommer att passa bra eftersom jag vill att Eats-o-matic skall få ett användargränssnitt mer likt en traditionell applikation än en webbapplikation. Ni vet, drag-and-droptab completion och liknande. Kort sagt, en Rich Internet Application…

Och eftersom jag inte är någon Javascript-guru men kan Java rätt så bra, så hoppas jag på att GWT:s javascriptabstraktion inte läcker allt för mycket, utan håller vad den lovar.

Sammanfattningsvis
Persistens: JDO
Webbramverk: GWT

Äventyr i molnet – del 2

Inledning

Google har en Eclipse-plugin som automatiserar bygge, integrationstest & driftsättning av applikationer för Google App Engine.

Men hur gör man om man liksom jag tycker att det skall gå att bygga och driftsätta från kommandoraden? Eller om man inte använder Eclipse?

Mitt svar är Maven. Tyvärr finns det inte (ännu) någon Mavenplugin, så det blir lite meckigt att få det att fungera.

Varför är detta viktigt?

Missförstå mig inte, jag tycker att det är suveränt att kunna bygga och testa inifrån Eclipse.

Men det är samtidigt väldigt bra att ha ett byggskript som går att köra obemannat från kommandoraden av följande anledningar:

  • Continuous Integration – bygg automatiskt från t.ex. Hudson efter varje incheckning
  • Dokumentation – ditt byggskript dokumenterar på ett körbart och förhoppningsvis portabelt sätt vad som behövs för att kunna bygga och leverera din produkt.
  • Stöd för andra IDE:er än Eclipse. IntelliJ till exempel har mycket bra stöd för Maven.

Varför inte Ant?

Google levererar Ant-stöd för GAE. Jag gillar dock Maven bättre, eftersom det är deklarativt. Beskriv vad du vill uppnå så tar Maven hand om resten. Convention over configuration. Med Ant måste du skriva XML för varenda litet steg i bygget. Ingenting sker automatiskt.

Så vad behövs då för att bygga och integrationstesta med Maven?

Följande förutsättningar måste vara uppfyllda för att det skall gå att 1) bygga, 2) integrationstesta och 3) driftsätta till GAE med hjälp av Maven:

  1. GAEs jar-filer måste vara nedladdningsbara från något Maven-lager (eng. repository).
  2. GAEs integrationstestmiljö måste finnas tillgänglig för Mavens integrationstestfas.
  3. Maven måste instrueras hur man laddar upp den färdiga war-filen till GAE för driftsättning.

Tyvärr är det ingen av dessa punkter som uppfylls på ett bra sätt i dagsläget!

Det finns dock sätt att lösa det:

  1. GAE-jarerna kan installeras i ditt lokala Maven-repo med ‘mvn install-file …’ eller (om ditt företag har ett eget Maven-lager) ‘mvn deploy-file …’
  2. Maven kan delegera till Googles Antskript.

Steg 1 är trivialt, och behöver bara göras en gång per maskin och GAE-version. Steg 2 är det meckiga. En hel del XML blir det…

Hav tröst!

Google brukar publicera sina artefakter på det centrala Maven-repot. GAE-jarerna kommer att finnas där också. Dock oklart när.

Google App Engine-killarna jobbar ihop med "Mr Maven" – Jason van Zyl på Sonatype – med att ta fram en riktigt Maven-plugin som täcker hela utvecklingskedjan.

Så därför har jag bestämt mig för att strunta i integrationstest & deploy från Maven så länge. Jag nöjer mig med att kunna göra det inifrån Eclipse. Projektet är trots allt ett hobbyprojekt, och därmed kan man lägga byggribban lägre.

Härnäst: val av webbramverk och persistens-API