I ett av våra projekt behövde jag ”tvätta” data som kom in via importer från diverse externa källor. Tvättningen består av att ta bort HTML-element såsom script-taggar, styling-attribut och för att ge ett bättre skydd mot XSS.

Då hittade jag jsoup som är ett litet javabibliotek för att enkelt kunna parsa/tvätta HTML

Länkar:

String unsafe = "<p><a href='http://example.com/'>Link</a></p>";
String safe = Jsoup.clean(unsafe, Whitelist.basic());
// now: <p><a href="http://example.com/" rel="nofollow">Link</a></p>

Stänga taggar:

String dirty = "<p>Paragraph that is <p>not closed";
String clean = Jsoup.clean(dirty, Whitelist.basic());
// now: <p>Paragraph that is</p><p>not closed</p>

Tabeller:

String dirty = "<td>This is a table col</td>";
String clean = Jsoup.clean(dirty, Whitelist.basic().addTags(
    "table", "tr", "td", "th"));
// now: <table><tr><td>This is a table col</td></tr></table>

jsoup känns snabbt och är ett trevligt ramverk som är enkelt att använda och funkar bra för att ”tvätta” HTML. Jag testade även JTidy och htmlcleaner men de kändes inte lika lätta att använda och jsoup hade precis den funktionalitet jag behövde. En annan fördel med jsoup är att det enkelt går att ladda hem biblioteket som en Maven-artefakt.

<dependency>
  <!-- jsoup HTML parser library @ http://jsoup.org/ -->
  <groupId>org.jsoup</groupId>
  <artifactId>jsoup</artifactId>
  <version>1.3.2</version>
</dependency>

Rekommenderas!

Så här i semestertider så är det inte helt ovanligt att man hamnar på nåt ställe som saknar bredbandsuppkoppling. I det här tipset så tänkte jag visa hur enkelt du kan använda din Androidtelefon som modem till din dator via USB tethering. Jag själv har en HTC Hero med Android 2.1 och på datorn har jag Ubuntu 10.04. (Läs mer…)

Grunden i varje webbprojekt består av en databas. I de flesta fall rör det sig om en klassisk relationsdatabas i form av Mysql eller motsvarande. Denna arkitektur är välkänd, mogen och har tjänat oss väl, men på senaste tiden har uttrycket ”NoSQL” hörts mer och mer. Bakom uttrycket döljer sig en rad olika typer av databaser som bygger på andra paradigm än den klassiska relationsdatabasen, i denna artikel tänker jag ge en översikt av dokumentdatabasen CouchDB

CouchDB

Lite kortfakta:

Vad är en dokumentdatabas?

Föga förvånande lagrar en dokumentdatabas sitt data i form av dokument. I CouchDB:s fall är dokumenten JSON-strukturer:

    {
        "_id" : "henrik_lundgren",
        "_rev" : "revision",
        "name" : "Henrik Lundgren",
        "company" : "Cygni AB",
        "skills" : ["Java", "Spring", "CouchDb", "JSON"]
    }

En distinkt skillnad gentemot en relationsdatabas är att CouchDB är schemalöst, dvs man definierar inte dokumentens struktur i förväg, man kan lagra vad som helst när som helst. Det enda kravet är att dokumenten innehåller ett id fält och ett revisionsfält: ”_id” respektive ”_rev”

id identifierar dokumentent och måste vara unikt, revision populeras av databasen och används för att identifiera eventuella uppdateringskonflikter.

Notera att det går utmärkt att lägga till nya fält i enskilda existerande dokument; skulle jag vilja lägga till ett email fält i dokumentet ovan behöver jag inte uppdatera alla andra dokument i databasen med detta nya fält. I en relationsdatabas skulle jag vara tvungen att lägga till en kolumn för alla rader i tabellen och låta det vara null i de fall där jag inte har tillgång till emailadressen.

När man hanterar dokument i CouchDB hanterar man alltid dem i sin helhet, det går inte att uppdatera ett fält enskilt, utan man måste skriva ner en ny version av hela dokumentet. Dessa operationer är atomära, dvs hela dokumentet sparas eller inte alls, man kan t ex inte få korrupta eller förstörda dokument om förbindelsen till databasen bryts mitt i en skrivning.

Hur ställer man frågor när det inte finns nån SQL?

Den kanske svåraste nöten att knäcka för en gammal SQL-räv är att i CouchDB definierar man sina frågor i javascript. Dessutom måste man definiera dem i förväg!

I CouchDB kallas dessa funktioner vyer och ser ut så här:

{"_id":"_design/Sofa",
    "views":{
        "by_skill": {"map": "function(doc) {
            for (var i in doc.skills) {
                emit(doc.skills[i], doc._id);
        }}"
    }}
}

Noga räknat så består en vy av en map funktion och en reduce funktion (ej obligatorisk). CouchDB använder allstå map/reduce algoritmen när vyer byggs upp.

Fördelen med att vyerna är fördefinierade är att resultaten ligger färdiga på disk, dvs uppslag mot en vy blir mycket effektiva. När ett dokument ändras eller läggs till så räknas bara den del av vyn som påverkas av dokumentet om.

Nackdelen kan vara att vyerna kan ta mycket plats, diskutrymme är ju som tur är billigt.

REST-gränssnittet

All interaktion med CouchDB sker via http-anrop. Vill man hämta upp ett dokument gör man helt enkelt ett GET-anrop:

GET http://127.0.0.1:5984/employees/henrik_lundgren

ger svaret:

{"_id":"henrik_lundgren","_rev":"1-2902191555","name":"Henrik Lundgren","company":"Cygni AB", "skills": ["Java", ..., ...osv,]}

Det hela är rätt enkelt, vill man spara ett dokument använder man PUT eller POST och vill man radera ett dokument anropar man med DELETE.

Replikering

CouchDB har mycket bra stöd för replikering. Ändringar gjorda i en databas kan enkelt replikeras ut till en annan databas genom ett http-anrop:


POST /_replicate HTTP/1.1
{"source":"database","target":"http://example.org/database"}

Anropet ovan kommer överföra alla dokument från källan till måldatabasen http://example.org/database. Notera att endast skillnaderna överförs.

Vill man synka åt ändra hållet är det bara att vända på ”source” och ”target” i anropet ovan. Det går även att sätta upp kontinuerlig replikering.

Om replikeringen skulle avbrytas av någon anledning kan den återupptas genom ett nytt replicate-anrop.

Slutsats

Detta var som sagt en kort introduktion till CouchDB och jag hoppas att du blivit intresserad att pröva på denna trevliga databas.

CouchDB innehåller mycket mer än vad som täckts av denna artikel och nedan hittar du länkar för vidare läsning:

Hittade en bra artikel om RESTful URI:s på http://redrata.com/restful-uri-design/

Där beskrivs alltifrån REST-basics till en mängd best practices gällande REST, URI-design och resurstänk.

Några exempel är:

  • Vad är en RESTful URI?
  • Tips för att skapa bra URI:er
  • Saker att undvika vid REST-design
  • Personliga URI:s såsom http://somedomain.com/calendar/my-calendar
  • Suffix (ex file.xml) vs Accept Header
  • Flera URI:s mot samma resurs
  • Praktiska tips om hur URI:n kan designas (plural vs singular etc)
  • …plus mycket mer

Värt att läsa tycker jag!

Läste på InfoQ att en första publik version av EGit har releasats. EGit är en Eclipse-plugin för Git som vi tidigare diskuterat här på stacktrace.se.

Se våra tidigare inlägg om Git-tricks eller en mer utförlig artikel om Distribuerad versionshantering med Git.

Jag har testat EGit och den funkar bra. Dock föredrar jag personligen att använda prompten/shellet för push, pull, branch och commit men EGit medför dock att det blir väl synligt i Eclipse vilka filer som inte är versionshanterade, vilka filer som är modifierade etc.

Nästa sida »