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.

zondag 21 oktober 2007

Java ME zal verdwijnen


Volgens guru en über-nerd James Gosling zal Java Micro Edition, de mobiele variant van Java langzaam maar zeker verdwijnen. Aangezien mobiele apparaten over steeds meer rekenkracht beschikken zal Java ME steeds meer met Java SE samensmelten. Zo bevat Java FX Mobile al bijna de volledige API van Java SE. "We're trying to converge everything to the Java SE specification. Cell phones and TV set-top boxes are growing up," Aldus Gosling "That convergence is going to take years."

Bron: CNet

maandag 15 oktober 2007

Fout: object vereist


Wie kent het niet? Je bent een stuk javascript code aan het maken en tijdens het testen verschijnt de foutmelding "fout: object vereist". Je krijgt dan de vraag of je wilt beginnen met foutopsporing en je bent dan eigenlijk altijd geneigd om op "Nee" te klikken, wetende dat de andere optie een of ander wazig programma start om vervolgens te crashen of zo. Voor de gein moet je eens op "Ja" drukken en dan de Microsoft Script Editor starten. Deze loopt door de code heen en stopt op de plaats waar de fout zit. Van hieruit kun je een heel aantal dingen controlleren. Zo kun je variabelen in javascript controlleren, hun waarden inzien en hun onderliggende structuur doorlopen. Zo kun je vrij goed opsporen waar de fout zit. Stiekem best handig dus.

zondag 14 oktober 2007

Effecten in swing


Tijdens mijn ziekte vorige week heb ik eens uitgeprobeerd hoever ik nou kan gaan in met Java Swing custom painting en geprobeerd om een effect na te bootsten wat ik ooit in assembler op school had geschreven. Dit effect bootst vuur na door middel van een vrij eenvoudig algoritme. Later meer hierover.

Om dit te bouwen heb ik een abstracte class gedefinieerd die de java.awt.Paint interface implementeert, zodat op eenvoudige wijze het scherm gevuld kan worden dmv setPaint op het Graphics object en een fillRect call.
Ik ga niet elke class bespreken hoe deze werkt, dit kun je me, als je het niet volgt, natuurlijk altijd vragen :).

De Effect class ziet er als volgt uit:





public abstract class Effect implements java.awt.Paint {

private final EffectListener listener;
protected DataBuffer db;
protected SampleModel model;

Timer effectTimer = new Timer(30, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
buildNextFrame();
listener.nextFrameReady();
}
} );

protected abstract void buildNextFrame();
protected abstract SampleModel createModel();
protected abstract DataBuffer createBuffer();

public DataBuffer getBuffer() {
if (this.db == null) {
this.db = createBuffer();
}
return this.db;
}

public SampleModel getModel() {
if (this.model == null) {
this.model = createModel();
}
return this.model;
}

public Effect(EffectListener l) {
if (l == null) throw new IllegalArgumentException("l == null");
this.listener = l;
this.effectTimer.start();
}

public interface EffectListener {
void nextFrameReady();
}

@Override
public abstract PaintContext createContext(ColorModel cm,
Rectangle deviceBounds,
Rectangle2D userBounds,
AffineTransform xform,
final RenderingHints hints);


@Override
public int getTransparency() {
return Transparency.OPAQUE;
}

}




Naast de definitie van het effect is er ook een Swingcomponent nodig dat dit effect laat zien, deze ziet er als volgt uit:




public class EffectPanel extends JPanel {

private Effect effect;

public EffectPanel() {
super.setOpaque(true);
}

@Override
protected void paintComponent(Graphics g) {
if (this.effect == null) return;
((Graphics2D) g).setPaint(this.effect);
g.fillRect(0, 0, getWidth(), getHeight());
}

public Effect getEffect() {
return this.effect;
}

public void setEffect(Effect effect) {
this.effect = effect;
}

}




Dit is alles wat we nodig hebben om een leuk effect op te kunnen bouwen in swing.
Het geheel is 100% compatible met swing en dit zou direct in elke applicatie geplugged kunnen worden door een bestaand JPanel te vervangen door het EffectPanel.
Aan het effectPanel kunnen gewoon op normale wijze andere Swingcomponenten worden toegevoegd layoutManagers geset worden etc.


Dit frameWork zou dus als volgt gebruikt kunnen worden, belangrijk is dat er aan het effect een listener wordt gekoppeld die het scherm opnieuw tekent als er een nieuw frame beschikbaar is. In dit geval heeft de effect-class een static methode die de "dirty region" bepaald.



public class EffectPanelTest {

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final EffectPanel p = new EffectPanel();
p.setEffect(new FireEffect(new Effect.EffectListener() {
@Override
public void nextFrameReady() {
p.repaint(FireEffect.getRepaintRectangle(p));
}
} ));
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(340, 200);
f.setContentPane(p);
p.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.anchor = c.NORTH;
p.add(new JButton("North button"), c);
c.anchor = c.SOUTH;
c.weighty = 1;
c.gridy = 2;
p.add(new JButton("South button"), c);
f.setVisible(true);
};
} );
}

}


Meer over het algoritme

Het originele algoritme werkte als volgt: vul de onderste 2 regels van de schermbuffer met willekeurige pixelswaarden tussen 0 en 255. Loop daarna de hele buffer af en tel de pixelwaarde onder, links van en rechts van op bij de huidige waarde van de pixel en deel dit door 4, trek er één af en plaats deze 1 boven de huidige positie terug in de buffer. Kopieer daarna de buffer naar het scherm en herhaal bovenstaande stappen.

Dit werkte toen goed omdat er gebruik werd gemaakt van 256 kleuren en een pallet aangepast op de kleuren. Dit zullen we dus moeten emuleren. Een ander verschil met toen is de resolutie van het scherm, nu op de pc waarop dit ontwikkeld is 1680x1050 toen 320x200. Dit verschil wordt nagebootst door een buffer met een vaste grootte te gebruiken en deze te schalen naar de benodigde grootte.




public class FireEffect extends Effect {

public FireEffect(EffectListener l) {
super(l);
initColors();
initBuffer();
}

Color colors[] = new Color[255];

public final static int height = 100;
public final static int width = 800;

Random r = new Random();

private void initBuffer() {
for (int x = 0; x < width; x++) {
for (int y = 0; y < height - 3; y++) {
getModel().setPixel(x, y, new int[] {0, 0, 0}, getBuffer());
}
}
}
/**
* initializeert het geemuleerde pallet
*/
private void initColors() {
for (int i = 0; i < 255; i++) {
int r = i - i / 16;
int g = i / 3;
int b = i / 8;
colors[i] = new Color(r, g, b);
}
}
int pixelBuffer[][] = new int[width][height];

@Override
protected SampleModel createModel() {
return new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, width, height, new int[] {0xFF0000, 0x00FF00, 0x0000FF});
}

@Override
protected DataBuffer createBuffer() {
return new DataBufferInt(width * height);
}

@Override
public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
final Rectangle2D userBounds, AffineTransform xform, final RenderingHints hints) {
PaintContext p = new PaintContext() {
@Override
public Raster getRaster(int x, int y, int w, int h) {
WritableRaster result = Raster.createWritableRaster(getModel(), getBuffer(), new Point(x, y));
for (int x1 = x; x1 < x + w; x1 ++) {
for (int y1 = y; y1 < y + h; y1 ++) {
// kopieer de waarden uit het geemuleerde pallet en schaal naar de grootte van userBounds
double userX = ((double) x1 / (double) userBounds.getBounds().width) * (double) width;
double userY = ((double) y1 / (double) userBounds.getBounds().height) * (double) (height - 3);
Color col = colors[pixelBuffer[(int) userX][(int) userY]];
result.setPixel(x1, y1 , new int[] {col.getRed(), col.getGreen(), col.getBlue()});
}
}
return result;
}
@Override
public void dispose() {
// doe hier niets, normaal vind hier cleanup plaats dit hoeft niet in deze demo
}
@Override
public ColorModel getColorModel() {
return new DirectColorModel(32, 0xFF0000, 0x00FF00, 0x0000FF);
}
} ;
return p;
}

@Override
public void buildNextFrame() {
for (int x = 1; x < width - 1; x++) {
for (int y = height - 2; y > height - 65 ; y--) {
int pixel1 = pixelBuffer[x - 1][y];
int pixel2 = pixelBuffer[x + 1][y];
int pixel3 = pixelBuffer[x][y];
int pixel4 = pixelBuffer[x][y - 1];
int newCol = (pixel1 + pixel2 + pixel3 + pixel4) / 4;
newCol = newCol < 2 ? 0 : newCol - 2;
Color c = colors[newCol];
pixelBuffer[x][y - 1] = newCol;
}
}
for (int x = 0; x < width; x+=4) {
for (int y = height - 3; y < height - 2; y++) {
int val = r.nextInt(255);
pixelBuffer[x][y] = val;
pixelBuffer[x + 1][y + 2] = val;
pixelBuffer[x + 2][y + 2] = val;
pixelBuffer[x + 3][y + 1] = val;
pixelBuffer[x + 2][y + 2] = val;
pixelBuffer[x + 1][y + 1] = val;
pixelBuffer[x + 2][y + 1] = val;
}
}

}

/**
* Geeft de dirty region terug zodat er niet te veel gerepaint wordt
* @param p
* @return
*/
public static Rectangle getRepaintRectangle(JComponent p) {
Rectangle repaint = new Rectangle();
double h = ((double) 65 / (double) FireEffect.height) * (double) p.getHeight();
repaint.y = p.getHeight() - (int) h;
repaint.x = 0;
repaint.height = (int) h;
repaint.width = p.getWidth();
return repaint;
}

}




Het belangrijkste in dit geval is natuurlijk niet de sourcecode, maak om het ding in het echt te zien.
Webstart demo:


maandag 8 oktober 2007

Web 3.0 of toch Web 2.1?


De afgelopen week heeft Jason Calacanis redelijk wat stof doen opwaaien met zijn definitie van Web 3.0.

Zijn definite:

"Web 3.0 is defined as the creation of high-quality content and services produced
by gifted individuals using Web 2.0 technology as an enabling platform."

Nu was hij niet helemaal serieus toen hij dit blogde, maar ik ben het er in ieder geval niet mee eens. In mijn ogen beschrijft zijn definitie namelijk meer een soort van Web 2.1, of Web 2.5 of in ieder geval een versie die < 3.0. Van Web 3.0 verwacht ik toch een nieuwe (revolutionaire manier om gebruik te maken van bestaande) techniek die tot gevolg heeft dat we op een andere manier met het web gaan werken.

Ik denk dat Jason de grote truuk van Tim O'Reilly even dunnetjes over wil doen. Toen Tim in het begin van deze eeuw met het probleem zat dat zijn internet conferenties helemaal niet meer werden bezocht (vanwege de net geklapte bubbel), was hij zo slim om de term Web 2.0 te bedenken. Veel mensen in de internet scene werden nogal blij van deze nieuwe hoop met als gevolg dat -BAM- zijn conferenties goed werden bezocht.

Dat Jason Calacanis' nieuwe startup Mahalo precies dat doet wat hij zegt dat Web 3.0 is, is op zijn minst nogal verdacht. Volgens mij is het gewoon allemaal een grote publiciteitsstunt van onze spindocter Jason. Blijkbaar wel een goede trouwens, want zelfs ik blog erover.

Damn toch erin getrapt! Volgende keer maar onze eigen Web 3.0 definite: "The web as a pipeline".

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.

WebSphere MQ voor beginners


Er zijn verschillende manieren/protocollen om berichten tussen systemen uit te wisselen. Een veel gebruikte manier is met behulp van het door IBM ontwikkelde WebSphere MQ. De configuratie van een MQ omgeving zorgt snel voor onduidelijkheid door de grote hoeveelheid aan elkaar te koppelen componenten, waaronder queues, transmission queues, queue managers, en channels. In deze wiki pagina zal ik een inleiding geven in hoe een MQ omgeving op te zetten.

Om het geheel wat inzichtelijker te maken zal ik dit doen aan de hand van een voorbeeld waarbij twee systemen, genaamd Alice en Bob, berichten met elkaar willen kunnen uitwisselen.


Terminologie

Ik zal eerst de belangijkste termen uitleggen.
message Aangezien Alice en Bob informatie willen kunnen uitwisselen zullen ze informatie moeten kunnen delen. Deze informatie kan worden opgedeeld in pakketjes. Eén zo'n pakketje informatie wordt en bericht oftewel message genoemd.

queue De uitwisseling van berichten kan worden gezien als het plaatsen van een bericht in een brievenbus/postvak van de ontvanger. Omdat meerdere berichten in één brievenbus geplaatst kunnen worden, vormen deze berichten een rij (welke overigens niet per definitie in volgorde van binnenkomst wordt afgewerkt). Je plaatst dus een bericht op een zogenaamde queue van de ontvanger. In ons voorbeeld kan Alice een bericht plaatsen op een queue van Bob en vice versa.

channel Als Alice een bericht in een brievenbus van Bob wil plaatsen, dan moet ze wel weten waar ze die brievenbus kan vinden én hoe ze er kan komen. Ze moet dus eigenlijk de weg weten naar Bob. Deze weg wordt ook wel kanaal, of channel genoemd.

queue manager Omdat Alice en Bob niet alles zelf willen regelen maken ze gebruik van hun eigen postbode. De postbodes van Alice en Bob kennen elkaar en hebben een weg (channel) afgesproken waarop ze elkaar kunnen ontmoeten om post over te dragen. De postbode beheert dus de post en zorgt dat deze op de plaats van bestemming aankomt door in contact te treden met andere postbodes. De postbode wordt ook wel queue manager (oftewel postvak beheerder) genoemd. Alice en Bob willen eventueel ook met anderen kunnen communiceren zodat ze meerdere brievenbussen (queue) kunnen hebben. Deze kunnen echter wel allemaal door één postbode beheerd worden.

transmission queue Als Alice een bericht naar Bob stuurt, geeft ze deze niet direct aan de postbode, maar legt ze deze in een postvak met de naam "UIT naar Bob". Op deze manier ziet de postbode dat er een bericht naar Bob gestuurd moet worden en verzorgt hij de aflevering. Hij gooit het bericht in zijn fietstas. Zo'n fietstas heet in WebSphere MQ wereld een transmission queue.

Er zijn nog enkele begrippen die ook van belang zijn om bovenstaande uitleg wat meer te detaileren:

request/response messages Vaak is het zo dat er de berichtenstroom een vraag/antwoord karakter heeft: de één vraagt en de ander antwoord. In dat geval is een vragend bericht een request message en het antwoord erop een response message.

correlation identifier Als Alice een vraag stelt aan Bob dan is het wel handig als ze weet welk bericht het antwoord op haar vraag bevat. Zeker als in het antwoord de vraag niet herhaald wordt of als ze snel achter elkaar meerdere vragen stelt zonder op antwoorden te wachten. Om dit probleem op de lossen nummert Alice alle vragen met een uniek nummer. Bob zet dit nummer boven ieder antwoord zodat Alice precies kan zien welk antwoord op welke vraag volgt. Dit unieke nummer wordt correlation identifier genoemd.

local/remote queue Een postvak kan lokaal zijn bij de gebruiker zelf, of op afstand bij een ander persoon. De postvakken van Alice zijn voor haar lokaal (local queues) en de postvakken van Bob zijn voor Alice op afstand (remote queues). Het postvak IN van Alice is voor haar dus een local queue en het postvak "Uit naar Bob" is dus een remote queue.

sender/receiver channel Zoals gezegd spreken postbodes met elkaar af om berichten over te dragen. Als Alice een bericht naar Bob stuurt volgt de postbode van Alice de versturende weg (sender channel) en de postbode van Bob de ontvangende weg (receiver channel). Dit is zo omdat er op sommige wegen slechts éénrichtsverkeer mogelijk is. De weg van Alice naar Bob is dus niet altijd dezelfde weg als die van Bob naar Alice.


De berichtuitwisseling

Stel dat Alice aan Bob een uitnodiging stuurt voor een etentje, dat vervolgens door Bob (hopelijk) positief wordt beantwoordt. Hoe gaat dat dan? We zullen het protocol stap voor stap doorlopen.


  1. Alice stelt het bericht op en plaatst het in haar postvak "UIT naar Bob";

  2. Alice' postbode pikt het bericht op en gooit het in zijn fietstas;

  3. Alice' postbode brengt het bericht via de voor hem bekende weg naar de postbode van Bob, die al staat te wachten;

  4. Alice' postbode overhandigt het bericht aan Bob's postbode;

  5. Bob' postbode plaatst het bericht in Bob's postvak IN;

  6. Bob leest het bericht;

  7. Bob stelt een antwoordbericht op en plaatst het in zijn postvak "UIT naar Alice";

  8. Bob's postbode pikt het antwoordbericht op;

  9. Bob's postbode brengt het antwoordbericht via de voor hem bekende weg naar Alice' postbode;

  10. Bob's postbode overhandigt het antwoordbericht aan Alice' postbode;

  11. Alice' postbode plaatst het antwoordbericht in Alice' postvak IN;

  12. Alice leest het antwoordbericht.

In MQ terminologie staat er het volgende. We doen het maar even in het Engels aangezien alle termen Engels zijn:


  1. Alice puts a message in her remote queue to Bob;

  2. Alice's queue manager picks up the message and puts it in the transmission queue;

  3. Alice's queue manager sends the message via the sender channel to Bob;

  4. Bob's queue manager receives the message via the receiver channel from Alice;

  5. Bob's queue manager puts the message in Bob's local queue;

  6. Bob reads the (request) message;

  7. Bob puts a (response) message in his remote queue to Alice;

  8. Bob's queue manager picks up the message and puts it in the transmission queue;

  9. Bob's queue manager sends the message via the sender channel to Alice;

  10. Alice's queue manager receives the message via the receiver channel from Bob;

  11. Alice's queue manager puts the message in Alice's local queue;

  12. Alice reads the (response) message

Bovenstaande opzet wordt weergegeven in het schema.

Een opstap naar meer: ISAAC bij de City Run Eindhoven

Aangezien het personeel van ISAAC graag voorop loopt, qua technische kennis maar ook op sportief gebied, zullen er een aantal 'ISAAC-ers', na weken van hard trainen, mee gaan rennen met de City Run Eindhoven van 6 kilometer welke plaats zal vinden vooraf aan de Marathon Eindhoven op 14 oktober 2007.

In 1993 vond voor het eerst de City Run plaats, met destijds 250 deelnemers. Inmiddels is dit onderdeel van de Marathon Eindhoven uitgegroeid tot een groot hardloopfeest met in 2006 maar liefst ruim 5800 deelnemers. Scholen, sportverenigingen, beginnende lopers en groepen die voor de gelegenheid zijn samengesteld leggen een ronde van 6 km af door het centrum van Eindhoven. Het parcours start om 10.30 uur en de route komt zelfs voorbij het ISAAC kantoor op de Stratumsedijk.

ISAAC wenst haar renners veel succes en bij deze een oproep om hen met z'n allen toe te gaan juichen tijdens het parcours of bij de finish en daarna gezellig te proosten op een goede gezondheid!

Parcours: http://www.marathoneindhoven.nl/nl/Deelname/City_Run_6km/Parcours

woensdag 3 oktober 2007

iPod touch: first contact


Heb vandaag ein-de-lijk mijn iPod touch mogen ontvangen van mijn chinese vrienden. Ik heb de afgelopen maanden al veel mooie gelezen en gehoord over de iPhone interface, maar nu ik hem zelf heb mogen ervaren moet ik zeggen: W-A-U-W. Wat een verschrikkelijk mooi scherm, wat een fijne bediening, wat een supervormgeving, wat een ingenieuze manier van browsen en wat heb ik al snel een lijstje van dingen die ik mis. En omdat ik niet hou van om de hete brei heendraaien: meteen maar mijn lijstje van dingen die ik graag verbeterd zou zien.

Ten eerste mis ik echt de mogelijkheid om ook afspraken aan mijn agenda toe te voegen. Dat is echt een enorme rotstreek van apple: een werkend stuk techniek in de vorm van de iPhone opzettelijk kreupel maken. Dan doet Microsoft met de nieuwe Zune dat toch een stuk beter: de oude Zune voorzien van alle functionaliteit die ook in de nieuwe is gestopt! Kijk, schaam je en leer, Apple.

Ten tweede zou ik graag mijn muziek kunnen streamen naar mijn airport express en naar mijn apple tv vanaf de ipod. Thuis zit ik niet altijd achter mijn pc en loop ik ook niet de hele tijd met die koptelefoontjes op, maar zo’n iPod kan je wel bij je dragen en dus volledige controle houden over de muziek of de podcasts die op dit moment uit de speakers knallen.

Ten derde zou ik graag wat meer invloed hebben op de vormgeving van de interface: de achtergond instellen, dat soort dingen. Iets wat wel kan in windows mobile als ik me niet vergis.

Ten vierde zou ik graag kunnen kiezen uit een berg third party apps: spelletjes, handige tools (skype of zo yeah ), een offline editor, etc. En niet alleen maar online, via safari, omdat ik niet altijd de beschikking heb over wifi (kom op NS, schiet eens op!). Maar ik denk dat dit toch redelijk snel van de grond zal komen: de vraag is te groot.

Ten vijfde zou ik graag 3G kunnen bellen… toch die tweede generatie iPhone maar kopen dan, ergens in mei of zo. Nog meer wachten. Pffff

dinsdag 2 oktober 2007

JOGL (Java OpenGl)


Lang geleden, toen ik nog op school zat, werd er beweerd dat Java goed was voor bussinessapplications maar voor grafische zaken te traag was. Daar waren dan wel uitvindingen als Swing voor het creëeren van grafische applicaties, en de Java3D API voor het creëeren van softwarematig gerenderde 3D applicaties in Java. Om hiermee te expirimenteren hebben we hier toen een project mee gedraaid, en ja, Java3D bleek echter wel degelijk retetraag. Maar er bestond wel degelijk een API die het mogelijk maakte om hardwareacceleratie te gebruiken in een Java applicatie, door middel van de heilige API: JOGL (Java OpelGL).

JOGL maakt het mogelijk de OpenGL libraries te gebruiken in de Java klassen van de JOGL API. Ik heb enkele demo's aanschouwt en ben lichtelijk in de ban geraakt van de mogelijkheden van deze API. Daarom wil ik gaan proberen hier wat mee te gaan expirimenteren, gewoon omdat ik het leuk vind, maar ook omdat het in de toekomst bruikbaar zou kunnen zijn.

Supported JBoss AS versies

De laatste weken valt het me op dat onze Java-goeroes bij JBoss wat strikter aan het worden zijn met het verlenen van support (zowel development support als production/maintenance support) op "niet enterprise"-versies van JBoss. Op zich begrijpelijk, omdat er intussen zo'n lading van versies en plugin-modules beschikbaar is dat het domweg ondersteunen van *alle* versies niet meer doenlijk is. We moeten daarom opletten dat we zo veel mogelijk gebruik maken van JBoss-versies die te downloaden zijn via network.jboss.com, waarvoor we onze JBoss Support login nodig hebben. In het kort komt het erop neer dat momenteel de "mixversie" 4.2.1. niet onder de support valt, en 4.2.0 die te downloaden is achter de login wél. Daarnaast valt de hele 4.0.X-range nog wel onder de ondersteuning.

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.