Posts tonen met het label Tutorial. Alle posts tonen
Posts tonen met het label Tutorial. Alle posts tonen

donderdag 3 september 2009

JavaScript laden zonder de browser te blokkeren


Er zijn heel veel factoren die invloed hebben op de snelheid waarmee een webpagina wordt afgebeeld. Zaken zoals het aantal requests per pagina, het wel of niet gebruik maken van een Content Delivery Network, het instellen van gzip voor bepaalde type content en een juiste plaatsing van scripts en stylesheets in de pagina, dragen allemaal bij aan de ervaring die de gebruiker heeft als hij de pagina opvraagt. Als de ontwikkelaar te veel van deze zaken fout aanpakt, dan zal hij de woede van de gebruiker op zijn hals halen en wellicht hevig bloedend ergens in een greppel treurig aan zijn einde komen.

Er zijn twee lekker pragmatische en niet te dikke boeken over deze onderwerpen geschreven die ik even wil aanstippen: “High Performance Web Sites” en “Even Faster Web Sites”, beide van Steve Souders (http://stevesouders.com/hpws/rules.php). Beide boeken zijn binnen ISAAC in ieder geval verplichte kost voor alle web develeopers.

In deze blogpost wil ik een van de technieken uit het tweede boek kort introduceren: “JavaScript laden zonder de browser te blokkeren”. Het probleem dat hier speelt is dat scripts die worden geladen m.b.v. een SCRIPT tag tot gevolg hebben dat de browser helemaal niets anders zal downloaden tijdens het laden en interpreteren van deze code. Dit alles kan resulteren in een significante verlenging van de laadtijd en dus tot een tragere pagina. Zonde, want browsers kunnen in theorie meerdere bestanden parallel downloaden.

De reden dat de browser niets anders downloadt is dat de JavaScript die op dat moment wordt gedownload de rest van de pagina kan wijzigen na executie. Het aantal en de volgorde van de andere resources kan afwijken van wat er in de oorspronkelijke HTML is gespecificeerd (bv met de document.write(…) constructie). Dit wijzigen van de HTML is in het overgrote deel van de gevallen helemaal niet aan de orde en resulteert dus in een onnodig lange laadtijd. Daarnaast is de volgorde waarin externe JavaScript bestanden zijn gedefinieerd in de HTML tevens de volgorde waarin ze moeten worden geëxecuteerd door de browser. Deze executievolgorde is eigenlijk niet van belang voor de volgorde waarin de scripts worden gedownload, iets dat tot nu toe alleen de ontwikkelaars van IE8, Safari 4 en Chrome 2 hebben begrepen: deze browsers ondersteunen het parallel downloaden van scripts wel. Andere resources worden echter wel nog steeds geblokkeerd.

In “Even Faster Web Sites” worden een aantal technieken geïntroduceerd die dit probleem (ten dele) oplossen. Ik zal deze hier kort introduceren. Voor de details verwijs ik echter door naar het boek zelf.

XHR Eval.
In deze techniek worden de scripts met een XMLHttpRequest gedownload en vervolgens met een aanroep van eval() geïnterpreteerd. Dit werkt: de browsers blokkeren het downloaden van de andere resultaten niet. Het grote probleem is echter dat je op deze manier alleen scripts kan laden die van hetzelfde domein komen als de pagina zelf.

XHR Injection
Deze methode lijkt enigszins op de voorgaande: het script wordt geladen mb.v. de XMLHttpRequest functie, maar wordt geëxecuteerd door een SCRIPT tag in de DOM te creëren en de gedownloade code daarin te injecteren. Deze methode is soms iets sneller dan het gebruik van eval(), maar lijdt onder dezelfde beperkingen.

Script in Iframe
Iframes worden parallel geladen met andere componenten op een pagina. Door in iframe’s HTML pagina’s te laden die verwijzen naar de gewenste scripts, worden deze scripts dus parallel gedownload. Ook deze techniek is beperkt tot scripts die op hetzelfde domein staan als de hoofdpagina zelf. Bovendien moet de code worden aangepast om een verbinding tussen de hoofd- en de iframepagina te leggen.

Script DOM Element
Als alternatief voor het initieel opnemen van een SCRIPT tag in de HTML, kan er ook een on-the-fly worden gecreëerd m.b.v. document.createElement(…). Deze tag wordt dan dynamisch voorzien van een src attribuut en vervolgens in de HTML geïnjecteerd. Deze methode is geschikt voor scripts die komen van een andere domein dan het domein van de pagina zelf.

Script defer
IE ondersteunt het DEFER attribuut bij de SCRIPT tag. Defer is een indicatie aan IE dat het gerefereerde script geen DOM wijzigingen zal uitvoeren en dat het niet meteen hoeft te worden gedownload. Dit heeft tot gevolg dat IE andere bestanden parallel met dit script zal downloaden. Het werkt echter alleen in IE en enkele nieuwe browsers.

Document.write Script tag
In deze techniek wordt net als bij de “Script DOM Element” methode een SCRIPT tag dynamisch aan de HTML toegevoegd, dit keer echter met een document.write() constructie. Het verschil is dat deze techniek alleen resulteert in het parallel downloaden van andere scripts, alle andere bestanden worden toch geblokkeerd.

Conclusie
Na het lezen van de technieken lijkt het redelijk simpel: kies altijd voor de “Script DOM Element” methode. De realiteit is echter niet zo eenvoudig. De keuze hangt af van het gewenste gedrag van de “busy indicators” in de browser (de visuele hints die aangeven dat er iets wordt gedownload) en van de wens om de download- en executievolgorde af te dwingen. Voor meer details over wanneer je nou precies wat moet kiezen verwijs ik je graag door naar hoofdstuk 4 van “Even Faster Web Sites”.

maandag 9 juni 2008

Een webservice in 5 minuten


EJB 3.0 en webservice annotations maken het mogelijk om webservices te maken, zonder alle details te kennen van WSDL of binding of wat dan ook. Sterker nog, je kunt in enkele minuten een webservice maken. Het enige dat je nodig hebt is een interface klasse, een implementatie klasse en een paar annotations. Laten we dit eens van dichtbij bekijken met het aloude “Hello World” voorbeeld. Maak een EJB 3.0 project en maak daarin allereerst de interface klasse.

package nl.isaac.ejb.service;

import java.rmi.Remote;

import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService
@SOAPBinding(style = Style.DOCUMENT)
public interface HelloWorld extends Remote {
String hello(String name);
}

Hierin zie je twee annotations staan. De eerste “@WebService” geeft simpelweg aan dat het om een webservice gaat. De tweede geeft aan welk soort SOAP binding je gebruikt, hierin heb je twee smaken “RPC” en “Document”. In het voorbeeld gebruik ik “Document”, maar in dit geval maakt het niet uit om hier “RPC” van te maken (Het verschil tussen document en RPC is grofweg gezegd dat RPC maar een enkel element als resultaat geeft en document een uitgebreid XML document terug kan geven). In de interface klasse staat verder alleen onze methode gedefinieerd. Let er wel op dat de interface jave.rmi.Remote extend. Nu kunnen we onze implementatie klasse maken.

package nl.isaac.ejb.service;

import javax.ejb.Stateless;
import javax.jws.WebService;

@Stateless
@WebService(endpointInterface = "nl.isaac.ejb.service.HelloWorld")
public class HelloWorldImpl {
public String hello(String name) {
return "Hello " + name;
}
}

Let erop dat, ondanks dat dit de implementatie klasse van een interface is, je deze niet implementeert met de code “implements HelloWorld”. Dit gebeurt in de annotation @WebService, die in deze methode zijn endpoint interface instelt. Deze verwijst naar de interface klasse die we zojuist gemaakt hebben. Onze methode wordt geïmplementeerd en voilá, een webservice is geboren. Deploy je project in JBoss en controleer voordat je een client maakt of je service draait door de WSDL file aan te roepen. Dit kun je doen door de URL van je project in IE in te voeren met daarachter “/HelloWorldImpl?wsdl”, dit zou je een XML document moeten tonen met alle details over de webservice.

woensdag 24 oktober 2007

Tutorial: Custom Taglib in JSP (Deel 3)


Welkom bij deel drie van de taglib tutorial. In dit deel nemen we een kijkje naar tags met een body.

Tot nu toe zijn alle tags in deze tutorial leeg geweest, dit is te herkennen aan het feit dat er maar één tag is die wordt afgesloten met een “/”. Kijken we echter naar HTML zijn de meeste tags niet leeg. Dit willen we met onze eigen taglib natuurlijk ook kunnen. De tag in dit deel van de tutorial gaat verder op de “Hello World” tags uit deel 1 en 2. Alleen printen we in dit deel de tekst “Hello World” in een stuk HTML code. De tag ziet er als volgt uit:

<tutorial:helloBody>
<p class=”cssClass” id=”helloWorld”>$_tekst</p>
</tutorial:helloBody>

Je ziet dat onze tag een begin-tag en een eind-tag, met daartussen HTML code. Ook is je misschien de tekst “$_tekst” gezien, op deze plaats wordt onze “Hello World” geplaatst. Aangezien dit gewoon via de replace() methode van String gaat had hier net zo goed iets anders kunnen staan, zolang we het maar netjes kunnen vervangen.

Om deze tag te kunnen verwerken zullen we hem eerst in onze taglib description moeten zetten. Dit gaat op dezelfde manier als onze allereerste tag, met een kleine wijziging.

<tag>
<name>helloBody</name>
<tag-class>nl.mysite.tags.HelloBodyTag</tag-class>
<body-content>JSP</body-content>
</tag>

In de bovenstaande code zie je de tag zoals deze wordt toegevoegd aan de taglib description. Zoals je ziet is deze inderdaad vrijwel identiek aan de code uit de eerste tutorial, echter waar eerder de waarde “empty” aan body-content werd meegegeven wordt nu de waarde “JSP” meegegeven. Dit betekend simpelweg dat de tag geen empty body heeft maar een body met daarin JSP code.

In onze tag handler zitten ook een aantal wijzigingen om de body van de tag te kunnen benaderen. Het eerste verschil is dat onze tag-handler geen subklasse is van javax.servlet.jsp.tagext.TagSupport maar van javax.servlet.jsp.tagext.BodyTagSupport. Ook hierin kun je dezelfde methoden overriden als normaal, maar je hebt er de methode getBodyContent() bij. Deze methode geeft een BodyContent object terug waarin de body staat.

In ons voorbeeld willen we de body ophalen een string (“$_tekst”) vervangen door “Hello World”. Dit doen we op de onderstaande manier:

BodyContent body = getBodyContent();
JspWriter out = body.getEnclosingWriter();
String data = body.getString();
data = data.replaceAll("\\$_tekst", "Hello World");
out.println(data);
body.clearBody();

In de eerste twee regels wordt de body en de JspWriter waarmee de body wordt geschreven opgehaald. De code in de body wordt in regel 3 in een string geplaats en in regel 4 gewijzigd. Daarna wordt de tekst geprint en de body wordt leeggemaakt.

donderdag 4 oktober 2007

Tutorial: Custom TagLib in JSP (Deel 2)


Het tweede deel van onze tutorial gaat over het maken van een custom tag met parameters. Wanneer je deel één van de tutorial hebt gemist en je afvraagt waar ik het over heb, klik dan hier om eerst het eerste deel te lezen voor je verder leest.

In het voorbeeld van deel één deden we niet meer dan de tekst “Hello World” afdrukken. Dit gaan we in dit deel uitbreiden met een parameter. Onze tag gaat er op de volgende manier uitzien:

<tutorial:helloworld name="Isaac Newton" />

En deze tag drukt de tekst “Hello [name]” af, in het bovenstaande voorbeeld wordt dus “Hello Isaac Newton” afgedrukt. Hiervoor moeten we de taglib description uitbreiden op de onderstaande manier.


<tag>
<name>helloworld</name>
<tag-class>nl.mysite.tags.HelloWorldTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>name</name>
<required>yes</required>
</attribute>
</tag>


De tag “attribute” wordt toegevoegd. Hieronder bevinden zich een aantal andere tags: “name” en “required”. Beide spreken voor zich, in “name” staat de naam van de parameter en in “required” staat of de parameter vereist is of niet. In dit laatste geval zal de tag handler een default waarde moeten bevatten. Daarnaast kunnen ook nog een tweetal tags voorkomen die we in dit voorbeeld niet nodig hebben: “rtexprvalue”, die aangeeft dat de return-type van expressies die de parameter doorgeven van een bepaald type moeten zijn of alles mag zijn (kan de waarden “true” of “false” bevatten) en de tag “type” wordt gebruikt om dit type aan te geven.

Na het aanpassen van onze taglib description kunnen we onze class file erbij pakken. Hieronder zie je dezelfde code als in de vorige tutorial, maar dan met de aanpassingen erin.


package nl.directa.tags;
import java.io.IOException;
import javax.servlet.jsp.tagext.TagSupport;

public class HelloWorldTag extends TagSupport {
private String name;

public int doEndTag() {
try {
pageContext.getOut().println("Hello "+name);
} catch (IOException ignored) { }
return EVAL_PAGE;
}

public void setName(String name) {
this.name = name;
}
}


Zo simpel is het! Je voegt een globale variabele toe en een set methode (let op de naamgeving volgens JavaBean conventies met de naam van de parameter erin verwerkt). In onze doEndTag methode gebruiken we de parameter om “Hello [name]” te printen.

Daarmee komen we aan het einde van het tweede deel in de custom taglib tutorial. In het volgende deel maken we een tag met een body, dat wordt lachen.

maandag 1 oktober 2007

Tutorial: Custom TagLib in JSP (Deel 1)


Dit is het eerste deel in een serie tutorials over het maken van een eigen tag library (taglib) in JSP. In dit eerste deel zal ik de basis van custom taglibs bespreken en hoe je een “Hello World” tag maakt. Na dit deel volgen in de komende dagen / weken nog vier delen in deze serie zodat alles over taglibs aan bod kan komen. Hou het blog dus in de gaten.

JSP tags en custom tags zorgen ervoor dat je de scriplet code in je JSP bestanden weg kunt laten (de code tussen <% %>). In plaats daarvan plaats je een tag die verwijst naar een stuk JAVA code in je backend. Dit zorgt voor een overzichtelijker JSP bestand. Het verminderd, namelijk, het “Spaghetti code” probleem dat je vaak tegenkomt in webapplicaties en maakt je code stukken leesbaarder.

Een taglib bestaat uit een aantal onderdelen. Allereerst wordt de code van de tag geplaatst in een tag-handler, een java klasse die erft van javax.servlet.jsp.tagext.TagSupport. Daarnaast wordt een beschrijving van de tag in een .tld bestand geplaatst, de tag library descriptor. Dit is een XML bestand die in de WEB-INF map geplaatst wordt. Uiteindelijk wordt in de web.xml de taglib gekoppeld aan een URL zodat de tags benaderbaar zijn in je applicatie.

Een “Hello World” tag maken

Voor onze “Hello World” beginnen we met het beschrijven van de tag in de tag library descriptor. In de WEB-INF map maken we een submap “/tlds” met daarin onze descriptor file “helloworld.tld”. Hieronder zie je de code die we in “helloworld.tld” plaatsen.

Helloworld.tld


<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library
1.2/EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>helloworld</short-name>
<uri>http://www.mysite.com/taglibs/helloworld</uri>

<tag>
<name&rt;helloworld</name>
<tag-class>nl.mysite.tags.HelloWorldTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>



In de bovenstaande code zie je op de eerste twee regels wat standaard XML code staan die je waarschijnlijk wel gewend bent van andere XML bestanden, er wordt verwezen naar de taglibrary dtd van Sun. Daarna wordt een “taglib” element gemaakt met daarin een paar standaard gegevens “tlib-version” (de versie van deze taglib) en “jsp-version” (de versie van de jsp taglib beschrijving). Bedenk voor de “short-name” een logische naam voor de taglib en maak ook van de “uri” een logische url. Onder deze header worden de tags geplaatst. In dit voorbeeld wordt een heel eenvoudige tag aan gemaakt. Hierin staat een naam (“name”), de Java klasse waarin de code voor de tag te vinden is (“tag-class”) en of de tag een body heeft (“body-content”).

Hierna openen we de web.xml en voegen het onderstaande toe in <web-app>.

<taglib>
<taglib-uri>http://www.mysite.com/taglibs/helloworld</taglib-uri>
<taglib-location>/WEB-INF/tlds/helloworld.tld</taglib-location>
</taglib>



Dit geeft aan waar de taglib te vinden is. Uiteindelijk moet er ook nog een implementatie komen. Hiervoor maken we een nieuwe klasse aan nl.mysite.tags.HelloWorldTag. Hieronder vind je de code van deze JAVA file.


package nl.directa.tags;
import java.io.IOException;
import javax.servlet.jsp.tagext.TagSupport;

public class HelloWorldTag extends TagSupport {
public int doEndTag() {
try {
pageContext.getOut().println("Hello World");
} catch (IOException ignored) { }
return EVAL_PAGE;
}
}



Zoals je kunt zien in onze HelloWorldTag klasse een subklasse van TagSupport. De methode doEndTag() wordt uitgevoerd op het moment dat de endtag van onze tag is bereikt en schrijft de tekst “Hello World” naar het scherm. Dit gebeurt via het object “pageContext”. Dit object kun je gebruiken om je JSP pagina te bereiken en kun je o.a. gebruiken om “out” te gebruiken, om het request object op te halen of om pagina’s te includen. In het voorbeeld wordt de JspWriter van de pagina opgehaald en hierin wordt een tekst geprint. De methode geeft een int terug, in dit geval “EVAL_PAGE”. Dit is een constante van TagSupport die aangeeft dat de rest van de pagina kan worden geëvalueerd. Natuurlijk zijn er nog meer mogelijke constante die teruggegeven kunnen worden, deze worden in de volgende delen belicht.

In je JSP bestand kun je de nieuwe tag pas gebruiken als je de taglib hebt toegevoegd aan de pagina met de onderstaande code.

<%@ taglib prefix="tutorial" uri="http://www.mysite.com/taglibs/helloworld" %>

Vervolgens kun je de tag op de onderstaande manier gebruiken.

<tutorial:helloworld />

Daarmee is het eerste deel van onze tutorial ten einde, in deel twee gaan we kijken hoe we ons "Hello World" voorbeeld interessanter kunnen maken.