Java Magazine #1 - 2013

40
Volledige samenwerking met DevOps Bouw je eigen robot Spoedcursus MongoDB Apache Camel: voor complete integratie mei/juni 2013 nr. 1 Onafhankelijk tijdschrift voor de Java-professional Java Magazine is TERUG Features MAGAZINE

description

Java Magazine is terug! Features: - Volledige samenwerking met DevOps - Bouw je eigen robot - Spoedcursus MongoDB - Apache Camel

Transcript of Java Magazine #1 - 2013

Page 1: Java Magazine #1 - 2013

Volledige samenwerking met DevOps

Bouw je eigen robot

Spoedcursus MongoDB

Apache Camel: voor complete integratie

mei/juni 2013 nr. 1

Onafhankelijk tijdschrift voor de Java-professional

Java Magazineis TERUG

Features

MAGAZINE

cover.indd 1 5/1/13 2:17 PM

Page 2: Java Magazine #1 - 2013

werkenbijordina.nl

ICTMAARDANVOORMENSEN

Ordina feliciteert alle Javanen met de terugkeer van hun lijfblad.

Zonder lijfblad ben je als Javaan niet compleet. Geweldig dus dat JAVA Magazine na anderhalf jaar weer van de persen rolt. Daarmee is de inhoud terug die je zo hebt gemist. Dat diepgaande artikel. Het internationale nieuws. Die handige tip. Alles wat je vak boeiend maakt. Geef je lijfblad nóg meer body! Wat mag volgens jou echt niet ontbreken in het nieuwe JAVA Magazine? Deel het met allemaal. En wie weet staat jouw bijdrage in het volgende nummer. Twitter je ideeën naar #mijnjava

OOKHETIDEEDATJEIETSHEBTGEMIST?

javaman.indd 2 25-04-13 16:19Untitled-1 1 29-4-2013 9:58:21

Page 3: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

VOORWOORD

Zoals de kop van dit voorwoord ook al zegt: Java Magazine is terug! Na een tijdje in print afwezig te zijn geweest, heb je nu dan eindelijk de hernieuwde en gerestylde editie van Java Magazine in handen. Ik had nu graag gewild dat bij het moment van open slaan het intro van “Eye of the Tiger” of de soundtrack van Rocky, zou klinken. Deze muziek illustreert namelijk exact ons enthousi-asme over Java Magazine en de NLJUG community. Iedereen heeft er heel veel zin in om alle leden van NLJUG weer te voorzien van de nodige kennis en kunde op Java-gebied middels het Java Magazine. Dit enthousiasme wordt vooral aan-gewakkerd door de grote betrokkenheid van de vele NLJUG-leden, die hielpen bij het realiseren van Java Magazine.

Naast het nieuwe magazine ook een nieuwe content manager. Inderdaad, ik noem mijzelf geen hoofdredacteur. Dit omdat het Java Magazine maar slechts een onderdeel is van een totaal hernieuwd aanbod aan diensten richting onze leden. Zo zullen ook de vertrouwde NLJUG Univerisity, de J Fall en de nieuwe nljug.org website [inclusief javamagazine info] onderdeel gaan uitmaken van mijn verantwoordelijkheden.Ik heb er zin in om samen met de leden, de programmacommissie, het bestuur en de redactieraad te werken aan toepasselijke info die jou als Java profes-sional kan ondersteunen. Het magazine is daarvan de eerste output. Wij [de redactieraad en ik] hopen dan ook echt dat deze uitgave jouw die ondersteu-ning dan ook weer kan bieden.

Wil je zelf ook bijdragen door iets te schrijven voor het magazine? Twijfel niet en neem contact met ons op! NLJUG bestaat immers door en voor de leden.Ik wens je in ieder geval veel leesplezier met het vernieuwde Java Magazine en hopelijk slaat ons enthousiasme ook op jou over!

Ramon Wieleman Content manager Java Magazine

Colofon Java Magazine 01-2013

Content manager:

Ramon Wieleman

Eindredactie:

Lilian Krijt

Auteurs:

Joop Lanting, Maikel Alderhout, Robert Scholte,

Hubert ten Hove, Eelco Meuter, Remko de Jong,

Marco Hebing, Anko Tijman, Frank Verbruggen,

Eric-jan Malotaux, Ben Ooms, Bert Ertman,

Frans van der Lek, Bert Jan Schrijver, Nanne Baars,

Peter Hendriks

Redactiecommissie:

Nanne Baars, Eelco Meuter, Bert Jan Schrijver,

Ben Ooms, Bert Ertman, Lucas Jellema, Tim Prijn

Vormgeving:

Britt Zaal, Jannemieke Duyzer, Jan Wesel

Uitgever:

Martin Smelt

Traffic:

Marco Verhoog

Media order:

Mirella van der Willik

Abonnementenadministratie:

Ingrid van der Aar, Tanja Ekel, Brigitte Hetem

Drukkerij:

Senefelder Misset, Doetinchem

Distributie:

Betapress

Sales:

Richelle Bussenius

E-mail: [email protected]

Telefoon: 023 752 39 22

Fax: 023 535 96 27

Java Magazine verschijnt 4 maal per jaar en is onderdeel

van het lidmaatschap NLJUG en kost € 39,50 (België € 40,50)

per jaar.

Naast het Java Magazine krijgt u gratis toegang tot de vele

NLJUG workshops en het JFALL congres. Het NLJUG is lid van

het wereldwijde netwerk van JAVA user groups. Voor meer

informatie of wilt u lid worden, zie www.nljug.org. Een nieuw

lidmaatschap wordt gestart met de eerst mogelijke editie

voor een bepaalde duur. Het lidmaatschap zal na de eerste

(betalings)periode stilzwijgend worden omgezet naar lidmaat-

schap van onbepaalde duur, tenzij u uiterlijk één maand voor

afloop van het initiële lidmaatschap schriftelijk (per brief of

mail) opzegt. Na de omzetting voor onbepaalde duur kan

op ieder moment schriftelijk worden opgezegd per wettelijk

voorgeschreven termijn van 3 maanden. Een lidmaatschap is

alleen mogelijk in Nederland en België. U kunt mailen naar

[email protected] of schrijven naar NLJUG BV, ledenadmi-

nistratie, postbus 3389, 2001 DJ Haarlem.

Op werkdagen kunt u bellen tussen 10 en 14 uur naar telefoon-

nummer 023–5364401. Verhuisberichten of bezorgklachten

kunt u doorgeven via www.hubstore.nl (Klantenservice).

Java Magazine is terug!

Voorwoord.indd 3 5/1/13 2:19 PM

Page 4: Java Magazine #1 - 2013

04

JAVA MAGAZINE

Voor elke serieuze Java-ontwikkelaar en/of -bedrijf werkend met Java-technologie is het een must om lid te worden van de NLJUG. Als u up-to-date wilt zijn en blijven is dit de manier om het te doen: word lid van de NLJUG op www.nljug.org. Het lid-maatschap kost € 39,- (incl. 6% BTW)

Voordelen van lidmaatschap

WIL JIJ IN 4 UUR ALLES TE WETEN KOMEN OVER DE LAATSTE IT TRENDS?

Kom dan op dinsdag 4 juni om 15:00 uur naar XebiCon in Fort Voordorp.

XebiCon brengt je helemaal up-to-date op het gebied van Agile, Big

Data, Continuous Delivery, DevOps, Mobile en Single Page Webapps!

XebiCon heeft ook dit jaar een spraakmakend programma met nationale en internationale sprekers. De conferentie start spectaculair met keynote speaker en extreem avonturier, Marc Sluszny. Zijn motto is:

Verwezenlijk je dromen, verleg je grenzen, overwin je angsten.

De conferentie zal worden afgesloten met de Agile Troublemaker en bedenker van Behavior Driven Development, Dan North!

Voor slechts € 50,- incl. BTW kun je deelnemen aan XebiCon. Op xebicon.nl vind je meer informatie over het programma en de locatie. Schrijf je snel in, want het aantal plaatsen is beperkt.

Graag tot ziens op XebiCon 2013!

Registratie op www.xebicon.nl Op www.xebicon.nl vind je ook informatie over het programma en de locatie. WORDT GEORGANISEERD DOOR XEBIA

#xebicon of volg @xebia

Xebicon 2013 adv-1.indd 1 26-04-13 08:47

Volledige samenwerking met DevOps

Bouw je eigen robot

Spoedcursus MongoDB

Apache Camel: voor complete integratie

mei/juni 2013 nr. 1

Onafhankelijk tijdschrift voor de Java-professional

Java Magazineis TERUG

Features

MAGAZINE

Gratis toegang tot NLJUG events

Gratis toegang tot NLJUG University sessions

Gratis 4 maal per jaar het Java Magazine

Werf.indd 4 5/1/13 2:22 PM

Page 5: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

INHOUDSOPGAVE

06 SPRING CONFIGURATIE Met @Configuration

10 BOEKBESPREKING Java Application Architecture

11 COLUMN Zieners

12 DEVOPS Het gehele implementatietraject

16 APACHE CAMEL Effectieve EAI

22 MONGODB De database van de toekomst?

27 LIBRARIES Libraries uitgelicht

28 RASPBERRY PI Ja-Pi, de eerste mobiele enterprise-server

32 GRAFISCHE USER INTERFACE Met Java en Sikuli

36 BESTUURSCOLUMN NLJUG Van het bestuur

38 TIPS & TRICKS Meer met Maven

SCHRIJVEN VOORJAVA MAGAZINE?

Ben je een enthousiast lid van NLJUG en zou je graag willen bijdragen aan Java Magazine? Of ben je werkzaam in de IT en zou je vanuit je functie graag je kennis willen delen met de NLJUG-community? Dat kan! Neem contact op met de redactie, leg uit op welk gebied je expertise ligt en over welk onderwerp je graag zou willen schrijven. Direct artikelen inleve-ren mag ook. Mail naar [email protected] en wij nemen zo spoedig mogelijk contact met je op.

Effectieve EAI met Apache CamelRequirements in IT-projecten en

requirements aan de integratie

met andere systemen zijn gevoelig

voor verandering. Snel reageren op

deze veranderingen kan cruciaal

zijn voor een succesvol project.

Enterprise Application Integration

(EAI) biedt alle kennis, technologie

en best practices, om uitbreid-

bare en onderhoudbare integratie

oplossingen te bouwen op een pro-

ductieve manier. In dit artikel zal

Apache Camel gebruikt worden om

te kunnen voldoen aan complexe

integratie vraagstukken.

28Ja-Pi, de eerste mobiele enterprise-serverEnkele leden van de redactiecommissie zijn gek van de Raspberry Pi en wilden wel

eens kijken wat er allemaal mogelijk is met deze mini-computer. Java Magazine zocht

uit hoe je met Java enkele led’s via een website kunt aansturen. Daarnaast heeft Ja-Pi,

de eerste mobiele Java enterprise-server, het levenslicht gezien. Alles is stap voor stap

uitgelegd, zodat je thuis ook zelf aan de slag kan gaan met Raspberry Pi.

16

12DevOps, de ‘zachte’ kantDevOps is een samenvoeging van

development en operations. Met

DevOps is er samenwerking moge-

lijk tussen ontwikkeling en beheer

om continuous delivery in een

organisatie te laten slagen. DevOps

implementeren in een organisatie

kent ‘harde’ en ‘zachte’ aspecten.

Java Magazine verkende de zachte

aspecten van een DevOps-imple-

mentatietraject aan de hand van

eigen ervaringen.

Inhoud.indd 5 5/1/13 2:25 PM

Page 6: Java Magazine #1 - 2013

06

JAVA MAGAZINE

Spring configuratie met @ConfigurationSpring configureren via een geannoteerde Java klasse. Voor de één een mooie oplossing en voor de ander is het een gruwel. Dit artikel gaat niet over deze discussie, maar over de werking en mogelijkheden van het configureren van de Spring container door middel van de @Configuration annotatie.

Dit artikel is gebaseerd op ervaringen met het gebruik hiervan en op bestudering van de javadocs van de besproken annotaties en classes. Doel is dan ook niet om volledig te zijn, daar biedt Spring voldoende docu-mentatie voor. Het doel is om een eenvoudig overzicht te hebben van de mogelijkheden, punten waar op te letten en mogelijk toepas-sing van de functionaliteit. Ook zullen we belichten hoe een Spring container omgaat met een mix van XML en op annotaties ge-baseerde configuratie. Als laatste tonen we hoe in een webcontext de Spring container te instantiëren wanneer je een geannoteerde configuratie hebt. De @Configuration annotatie biedt de moge-lijkheid om naast of zonder de reguliere XML configuratie een simpele Java klasse te anno-teren met @Configuration. In deze Java klasse kun je de Beans configureren zoals je in XML zou doen. Deze geannoteerde Java klasse is zelf gewoon een Bean zoals een @Component en kan als zodanig gebruikt worden. Sinds Spring 3.1 zijn er geen beperkingen tegenover XML configuratie, alles wat je in XML kunt definiëren, kun je dus ook in een Java klasse annoteren met @Configuration. Enkele voordelen van het configureren op deze manier zijn onder andere dat de confi-guratie door middel van Java geschreven is, mogelijke fouten eerder zichtbaar zijn (tijdens compileren), het mogelijk is Beans van een anonymous inner type te declareren en het conditioneel creëren van een Bean. De contai-ner kan prima overweg met een mix van XML

Ben Ooms is een gepassioneerde Java senior software engineer werkzaam bij Sogeti. en geannoteerde configuratie, het ene sluit

het andere niet uit. Om Java configuratie te kunnen gebruiken, moet naast de reguliere Spring afhankelijkhe-den ook CGlib toegevoegd worden wanneer je een Spring versie onder 3.2 gebruikt. Dit komt omdat CGlib door Spring als een optionele af-hankelijkheid gedefinieerd is. Naast Java con-figuratie wordt CGlib ook door Spring AOP ge-bruikt. De reden waarvoor CGlib noodzakelijk is, is omdat de @Configuration geannoteerde klasse een gewone bean is die daarnaast ook de context, scope en Bean semantiek moet weten. Hiervoor maakt Spring een CGlib proxy voor elke @Configuration Bean aan. Vanaf Spring 3.2 is deze afhankelijkheid niet meer nodig, en is de CGlib code van versie 3.0 geïntegreerd in Spring en te vinden in de org.springframework.cglib package. Doordat CGlib tijdens het opstarten dyna-misch functionaliteit toevoegt, zijn er twee eisen waar een @Configuration geannoteerde klasse aan moet voldoen: de klasse mag niet final zijn en er moet een default no args constructor zijn. De simpelste form kan er zo uitzien:

Package com.foo.confi g;@Confi gurationpublic class MyConfi gpublic MyConfi g()@Bean coffeeBean() Return new Coffee-Bean();

Spring2kolom.indd 6 5/1/13 2:31 PM

Page 7: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

SPRING CONFIGURATIE

Spring configuratie met @Configuration

In XML zou de configuratie er zo uitzien:

Om deze configuratie te laden in een XML geconfigureerde container, moet de wel-bekende (als je al met Spring annotaties werkt) context:component-scan of de context:annotation-config tag aanwezig zijn. Zoals je misschien al verwacht, is een @Configuration geannoteerde klasse inderdaad gewoon een bean zoals een @Component of soortgelijke geannoteerde klasse. Als je met de context:component-scan wil werken is dit in je XML voldoende:

Zoals getoond in bovenstaand voorbeeld, kun je in een bestaande XML gebaseerde Spring configuratie door middel van de context:component-scan Java gebaseerde configuratie toevoegen. Wil of kan je de component-scan niet gebruiken, dan is dat ook mogelijk door middel van de context: annotati-on-config en voeg je deze tag toe in je XML.

Daarnaast is het ook mogelijk om alleen op annotatie gebaseerde configuratie in te laden. Spring heeft hiervoor een tweetal bootstrap classes. De AnnotationConfigApplication-Context en de web versie AnnotationConfig-WebApplicationContext.De AnnotationConfigApplicationContext kan op drie manieren geïnstantieerd worden. De eerste manier lijkt op de manier zoals je dit met een XML gebaseerde Spring configuratie zou doen:

De tweede manier gebruikt de default con-structor en het scanning mechanisme:

<beans> <bean id=”coffeBean” class=”com.foo.config.CoffeBean” > </></ beans>

<context:component-scan />

<context:annotation-config />

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationCon-text(Configuratie.class);

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationCon-text();ctx.scan(“de.package.die.je.wil.scan-nen”);ctx.refresh();

Als laatste de manier die erg op de tweede manier lijkt maar de register methode gebruikt om de container te voorzien van de configuratie:

De AnnotationConfigWebApplicationContext is op dezelfde manieren te instantiëren als de XML variant. De op annotaties gebaseerde configuratie heeft twee annotaties om andere configuraties in te laden. Als je een andere Java geannoteerde configuratie wilt inladen, gebruik je de @Import annotatie. Met @ImportResource kun je een XML configu-ratie inladen. Tijdens het schrijven van de voorbeeld code, kwam ik er achter dat je hiermee moet uitkijken wanneer je meer dan een @Configuration geannoteerde klasse heb. Doordat een Java klasse met de @Configura-tion onderhuids ook een gewone Bean is, kun je een andere configuratie klasse ook door middel van @Autowired injecteren. Dit heeft als voordeel dat het meteen duidelijk is waar de gebruikte Bean geconfigureerd wordt. Het nadeel is echter dat hierdoor de beide configuratie klassen tightly coupled zijn. Een voorbeeld hiervan is bijvoorbeeld:

Externe properties kunnen geladen worden door middel van de @PropertySource annota-tie of door middel van de @Value annotatie met een geconfigureerde propertyPlacehol-derConfigurator. Als je de @PropertySource manier gebruikt, moet je ook een Spring Environment laden door middel van bijvoor-beeld @Autowired in de configuratie klasse. Daarna kun je de property inlezen met de getProperty(‘naam”) van de geïnjecteerde Environment klasse. Belangrijk om te weten is dat wanneer twee ingeladen properties bestanden dezelfde property bevatten, de waarde van de laatst geladen properties bestand gebruikt wordt en dat de properties alleen binnen een @Bean definitie te gebrui-ken zijn.

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationCon-text();ctx.register(ConfigA.class);ctx.register(ConfigB.class);ctx.refresh();

Gegeven een xml configuratie genaamd springapp.xml@Configuration@ImportResource(“springapp.xml”)public class MyConfigrest van de klasse...

Spring2kolom.indd 7 5/1/13 2:31 PM

Page 8: Java Magazine #1 - 2013

08

JAVA MAGAZINE

Met de PropertyPlaceholderConfigurator heb je twee keuzes. Als deze al in een XML gedefinieerd wordt, kun je direct aan de slag met de @Value annotatie om properties in te lezen. Mocht die er niet zijn, dan kun je deze ook instantiëren in de Java configuratie klasse. Om dit te doen moet je op klasse niveau door middel van de @PropertySource annotatie de locatie van het properties be-stand, een PropertyPlaceholderConfigurator bean definiëren en properties inlezen met @Value.Sinds Spring 3.1 kun je verschillende profie-len gebruiken. Met een profile creëer je een logisch bij elkaar horende Bean verzameling. Deze verzameling wordt alleen geladen wan-neer het profiel als actief wordt aangemerkt. Het activeren van een profile kan door middel van het toevoegen van een System property genaamd spring.profiles.active met als waarde een of meerdere profiel namen, of door de methode setActiveProfile aan te roepen. Vanaf Spring 3.1 is voor de XML versie aan de beans tag het attribuut profile gekomen en in een op basis van annotaties geconfigureerde container kun je de @Profile annotatie toevoegen. Interessant aan de profielen is dat je deze runtime kan laden.Zoals je kunt zien is de flexibiliteit erg groot

Gegeven een property file genaamd props.properties met een key genaamd propKey

@Configuration@propertySource(“props.properties”)public class MyConfig@Autowired Environment env

@Bean InjectedBean injectedBean() InjectedBean b = new Inject-edBean(); b.setProp(env.getProper-ty(“propKey”)); return b;rest van de klasse...

@Configuration@profile(“st”)public class MyConfigrest van de klasse...// Profiel laden in contextApplicationContext ctx = new annota-tionConfigContext();ctx.setActiveProfile“st”);ctx.refresh();

en kun je een Java configuratie op veel verschillende manieren gebruiken. Je kunt bijvoorbeeld binnen een bestaande XML geconfigureerde container met de compo-nent-scan of annotation-config Java confi-guratie toevoegen, of een bestaande XML gebaseerde container ombouwen tot een op annotatie gebaseerd container door gebruik te maken van de @ImportResource om zodoende een geleidelijke transitie te kun-nen maken. Na het maken van de voorbeeld code ben ik er achter gekomen dat hoewel een mix tussen XML en geannoteerde goed te doen is het de onderhoudbaarheid niet ten goede komt. Zeker wanneer je Spring profielen, XML en geannoteerde configura-tie combineert, moet je de geconfigureerde container goed testen op de aanwezigheid van de door jou verwachte Beans.

Beans zijn te definiëren door de @Bean annotatie toe te voegen aan een methode. Het interessante van een Bean annotatie is dat deze ook gedeclareerd kunnen worden in een niet @Configuration geannoteerde klasse. Let er wel op dat als de Beans ge-declareerd worden in een klasse die niet de annotatie @Configuration heeft, de scope niet gerespecteerd wordt.

De optionele attributen van de @Bean an-notatie zijn name, autowire, initmethod en destroymethod. Als er geen specifieke naam gegeven is aan de bean zal de naam

HET PROJECT KUN JE DIRECT GEBRUIKEN ALS EEN SPRING SANDBOX OM MET SPRING TE EXPERIMENTE-REN.

Spring2kolom.indd 8 5/1/13 2:31 PM

Page 9: Java Magazine #1 - 2013

SPRING CONFIGURATIE

JAVA MAGAZINE | 01 2013

hetzelfde zijn als de method. Dit is te veranderen door het attribuut name toe te voegen. Interessant is dat de name attri-buut een array van Strings accepteert om dus meerdere aliassen toe te kennen aan de Bean. Met het autowire attribuut geeft men aan of de bean attributen automatisch ge-injecteerd moeten worden. Standaard staat dit uit. De mogelijke andere waarden zijn net als bij een XML geconfigureerde contai-ner injectie door middel van bean type of naam. Met de init methode parameter kun je aangeven welke methode aangeroepen moet worden na instantiëring van de bean. De bruikbaarheid hiervan is discutabel, want hetzelfde kan worden gedaan door in de Bean methode body de bewuste methode aan te roepen op het object.

De destroy method parameter is wel iets bruikbaarder. Hiermee kun je, zoals de naam al aanduidt, aangeven welke method moet worden aangeroepen wanneer de Bean ge-destroyed wordt. Als je deze parameter niet meegeeft, gaat de Spring container standaard bij het destroyen op zoek naar een publieke no arg methode close() en voert het deze uit. Deze standaard kun je overrulen door een lege String destroy methode naam mee te geven. Wanneer je dit doet zal de aanwezige

close methode niet aangeroepen worden. In de javadoc staat een specifieke uitzon-dering waar je op moet letten wanneer je een Bean definieert die een BeanFactoryPo-stProcessor type retourneert. Omdat deze Beans meestal zeer vroeg in de container lifecycle benodigd zijn, kunnen ze storend werken bij het verder instantiëren van andere Beans. Het advies is dan ook om deze type Beans als static te definiëren. Mocht de Spring container deze type Beans instantiëren vanuit een methode die niet static is, dan zal er een waarschuwing in de log vermeld worden. Nadeel is echter dat deze Beans niet voor Bean scoping of AOP in aanmerking komen wanneer ze door middel van een static methode zijn geïnstantieerd.

Ik hoop dat je met dit artikel een goede indruk hebt gekregen van de mogelijkheden die beschikbaar zijn wanneer je Spring wil gebruiken met een configuratie door middel van annotaties. Op bitbucket kun je een ma-ven eclipse project uitchecken op https://bitbucket.org/bendh/spring-configuration-sandbox waarbij de in dit artikel besproken mogelijkheden gedemonstreerd worden. Het project kun je direct gebruiken als een Spring sandbox om met Spring te experi-menteren.

Ben jij ook eenChampions League speler?

Kijk voor onze vacatures op pagina 20/21 van dit magazine.

Advertentie

Spring2kolom.indd 9 5/1/13 2:31 PM

Page 10: Java Magazine #1 - 2013

10

JAVA MAGAZINE

BOEKBESPREKING

In de Java-wereld hebben we een stroom aan boeken over hoe je moet programmeren op de vierkante cen-timeter: wanneer je interfaces moet gebruiken in plaats van concrete ‘clas-ses’, hoe groot methods moeten zijn, over Dependency Injection, Visitors, Observers, Model-View-Controller en honderd andere patterns. Java-ontwikkelaars weten veel over het verdelen van een applicatie in logische lagen, of wanneer je een gelaagde applicatie juist beter kunt vermijden met bijvoorbeeld het CQRS (Command Query Responsibility Segregation) pat-tern. Er is ook genoeg geschreven over het definiëren van services en hoe je die moet groeperen in applicaties. Maar over het niveau daartussenin, hoe je een grote applicatie verdeelt in fysieke modules, is er gek genoeg verbazend weinig literatuur.‘Java Application Architecture: Modularity Patterns with Examples Using OSGi’ van Kirk Knoern-schild is zo’n boek. Het richt zich op fysiek ontwerp zoals hoe een software systeem verpakt wordt in installeerbare eenheden, welke ‘classes’ in welke module thuishoren en welke afhanke-lijkheidrelaties er tussen de modulen bestaan.Het boek is verdeeld in drie delen. Deel I definieert wat een module is (zeg maar een jar-file), welke aspecten daaraan zitten, de plaats van modules in de applicatiearchitectuur, de functie van modulariteit bij het beperken van complexiteit en hoe modulariteit her-gebruik van code kan bevorderen. Het eerste deel sluit af met een uitgewerkt

voorbeeld, waarin een eenvoudige maar monolithische applicatie in zeven stap-pen modulair wordt gemaakt. Deel II is een catalogus van achttien patterns, verdeeld in de categorieën base pat-terns, dependency patterns, usability patterns, extensibility patterns en utility patterns. Deel III tenslotte presenteert OSGi als het de facto enige beschikbare dynamische modulesys-teem voor Java. Het beschrijft hoe je de in het voorgaande deel gemodulari-seerde applicatie in een OSGi-omgeving kunt installeren, zodat de voordelen van een modulaire applicatie ook bij installatie en op runtime gerealiseerd kunnen worden. De achttien ‘Patterns Of Modular Architecture’ (POMA) in deel II vormen de kern van dit boek. Ze zijn beschre-ven op een manier die onafhankelijk is van Java of OSGi. Daardoor zijn ze breed toepasbaar in allerlei omgevingen, ook bijvoorbeeld .NET, al zal een .NET-ontwikkelaar waarschijnlijk afgeschrikt worden door het woord ‘Java’ in de titel. Hoewel OSGi al veel langer intern wordt toegepast in applicatieservers, is het pas bij recente versies mogelijk om daarop ook OSGi-applicatiebundles te installeren. En die versies hebben nog lang niet overal hun weg gevonden naar de productieomgevingen. Toch is het nuttig om de patterns ook nu al toe te passen, bijvoorbeeld op de verdeling van een systeem in maven modules. Wanneer OSGi (of Jigsaw) dan beschik-baar komt, zal het weinig moeite kos-ten om de applicatie daarvoor geschikt te maken.Opvallend genoeg maakt de auteur bij het bouwen van de modules in de voorbeelden gebruik van ant als build tool, terwijl veel Java-ontwikkelaars jaren geleden al ant verwisseld hebben voor maven. Het waarom daarvan wordt duidelijk, wanneer Knoernschild laat zien dat je voor het refactoren van

de modulestructuur van een applicatie alleen maar het ant build-script hoeft aan te passen. In maven is dat veel moeilijker. Daar zijn source files gegroe-peerd naar modules. Bij refactoring van de modulestructuur betekent dit dat je de source files moet verplaatsen, ook in de versiebeheer repository, wat refacto-ring veel moeilijker maakt.Robert C. Martin schrijft in het voor-woord dat dit boek alleen ‘hard core stuff’ bevat en geen ‘fluff’. Dat is naar mijn mening niet helemaal waar, want de auteur gebruikt vrij veel woorden om te zeggen wat hij wilt en herhaalt zichzelf vaak. Dat doet overigens weinig af aan de waarde van het boek. Vooral de patterns van modulariteit zijn onschatbaar en verdienen het om grondig bestudeerd en misschien wel uit het hoofd geleerd te worden.

Boekbespreking

Eric Jan Malotaux is werkzaam bij Ordina als software architect.

Java Application Architecture

REFERENTIEJava Application Architecture: Modularity Patterns with Examples Using OSGi / Kirk Knoernschild. - Prentice Hall, Upper Saddle River, NJ, 2012.

Boekreview.indd 10 5/1/13 2:35 PM

Page 11: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

COLUMN

ZienersZieners zijn mensen die zien wat wij niet zien. Net zoiets als paragnosten, maar dan beperkt tot toekomstige ontwikkelingen. En even onbruikbaar. Toch zijn er hele volksstammen die in ze geloven, ja, ook in dit ontwikkelde gebied. Ze kopen of verkopen direct de aangewezen goederen of aandelen, kiezen of versmaden de geduide contacten of negeren, dan wel storten zich op de voorspelde routes.

Joop Lanting, Amsterdam 1947.Gepensioneerd systeemprogrammeur, een der eersten in Europa met UNIX (1977), was onder meer werkzaam aan de Universiteit van Amsterdam, MultiHouse en Unisys.

Hoe het werkt? Nou, zet 6 mensen op een rij, laat ze elk een nummer kiezen uit 1-6, gooi met een dobbelsteen en er is er altijd een die BINGO roept. Herhaal dat een paar keer in het groot en je hebt trouwe volge-lingen. Een en ander is ooit door Hitchcock verfilmd! Mijn vader had ooit een boek dat heette ‘Auto, Boot en Vliegtuig’ (jammer, het is zoek geraakt), dat vol met voorspel-lingen stond m.b.t. het ‘toekomstig’ verkeer. Gelukkig stamde het uit de dertiger jaren, dus als kleutertje kon ik zelf al vaststellen dat het allemaal onzin was. Sindsdien heb ik heel wat neergepende fantasieën gelezen en ik ben er inmiddels aan gewend geraakt dat de boeiendste verhalen de plank het hardst misslaan. Mooi voorbeeld: ‘De reis naar de maan’ van Jules Verne: helemaal gebaseerd op een door hem gelezen, maar totaal verkeerd begrepen, artikel in een weten-schappelijk tijdschrift.

En in de automatiseringswereld? Dat is toch een gemeenschap van nuchtere lieden? Tja... < In 1966 ging ik, vers van de middelbare

school, een cursus volgen bij IBM. Op de laatste dag, na een examentje, kregen we nog een demonstratie van rekenkracht te zien, waarbij de rondleider trots verkondig-de dat “programmeren nu niet meer nodig was: er was nu RPG”. Gewoon een formu-liertje invullen en de resultaten rolden uit de regeldrukker. Je moet er niet aan denken anno 2013.

< In 1983 had ik mij tegoed gedaan aan COBOL, FORTRAN, ALGOL en C. Maar het was allemaal verloren tijd want “het Amerikaanse D.o.D. had een nieuwe alles vervangende taal uitgebracht: ADA”. Ja, het ministerie van oorlog deed ook nuttige dingen. Ik moet toegeven dat het nog schijnt te bestaan, ik zou alleen niet weten waar.

< In 1988 hoorde ik van mijn werkgever dat alle (ALLE!) terminals en computers gingen worden vervangen door een aantal CASE workstations: teken een paar stroomdia-grammen en klaar. Kort daarna stonden we wel voor een faillissement. Ik wist nog net op tijd weg te komen ...

< In 1997 ging ik zelf in de fout: op een NLUUG congres werd JAVA geïntroduceerd. Mijn gebruikelijk congresverslag vermeldde o.a. dat “JAVA niets nieuws bracht sinds PASCAL” en “meer een politiek dan tech-nisch item was in de strijd tussen SUN en MICROSOFT”. Drie jaar later schreef, dacht en was ik JAVA; tot op de dag van heden.

< En dan het allerergste wat me ooit is over-komen: DE RETRO-VISIONAIR:In 1971 stormde een technicus het lab waar ik werkte binnen met “weg met alle disks, er komt nu TUBE-MEMORY”: data bits op de voorkant van een TV-buis, geschre-ven en gelezen met de lichtsnelheid. Niets meer van vernomen, tot... In 1979 bezocht ik het Science Museum in Londen (Kensington), een museum waar je weken in kunt ronddwalen. Op de 4e verdieping van het middenschip is het automatise-ringsmuseum. En wat glimlachte mij daar vanachter de vitrine ruit toe? TUBE-MEMO-RY by Williams, Ferranti 1954! Ik voelde me even als een archeoloog die een afbeelding van een iPhone tussen de hiërogliefen ziet. ;JOOP!

TUBE-MEMORY

by Williams,

Ferranti 1954.

Column Zieners.indd 11 5/1/13 2:35 PM

Page 12: Java Magazine #1 - 2013

12

JAVA MAGAZINE

Wij kunnen binnen de Java-wereld de DevOps-belofte laten slagen met behulp van continuous integration tools zoals Jenkins en Maven, met kwaliteitstools zoals JUnit, Sele-nium en FitNesse en met nieuwe continuous deployment tools en plugins zoals DeployIt, Build Pipeline en Puppet. Op technisch gebied zijn we er klaar voor, maar is dat genoeg?Om een nieuwe beweging in een organisatie te laten landen, is er meer nodig dan alleen de techniek op orde te hebben. Het is goed om vanuit verschillende perspectieven naar de implementatie van DevOps in de organisatie te kijken. De zeven aspecten hiervan komen terug in het honingraatmodel (figuur 1) dat wij hanteren. Door aan alle aspecten van het model aandacht te besteden bij het doorvoe-ren van DevOps, zal deze nieuwe werkwijze sneller en gemakkelijker in de organisatie landen. Bij het implementeren van DevOps hebben we verschillende obstakels moeten overwinnen. Daar zaten uiteraard technische problemen bij, maar we stuitten ook op organisatorische problemen die op het model zijn te projec-teren. Vanuit onze praktijk geven we aan de hand van vijf vragen, inzicht in de grootste niet-technische belemmeringen die we tegen zijn gekomen en hoe we daarmee zijn omgegaan.

Aan de slag met DevOpsDe ‘zachte’ kant belicht

‘DevOps’, een samentrekking van development en operations, is het logische vervolg van Agile: een samenwerking tussen ontwikkeling en beheer om continuous delivery in een organisatie te laten slagen. DevOps implementeren in een organisatie kent ‘harde’ en ‘zachte’ aspecten. In dit artikel verkennen we de zachte aspecten van een DevOps-implementatietraject aan de hand van onze eigen ervaringen.

Hoe creëer je een gezonde omgeving waarin je met DevOps aan de slag kunt?Een gezonde omgeving voor DevOps is een omgeving waarin iedereen de voordelen draagt die DevOps te bieden heeft. Dat wil zeggen dat er wederzijds respect is en ook voor elkaars kennis en kunde. Snelle feedback wordt gewaardeerd, van zowel het systeem als van elkaar. Daarnaast is het essentieel dat er in een synergistisch proces waarde wordt opgeleverd, en dat we kunnen reageren op voortschrijdend inzicht.

Anko Tijman is Thoughtleader Agile bij Ordina en spreekt en publiceert regelmatig over Agile- onderwerpen. Hij heeft recent vanuit een beheerorganisatie meegedraaid in een Agile-team.

Frank Verbruggen is Java Software Architect en ‘DevOps-coach’ bij Ordina. Hij leidt op dit moment een ‘DevOps-team’ bij de semi-overheid.

Figuur 1: Het honingraatmodel

DevOps.indd 12 5/1/13 2:36 PM

Page 13: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

Aan de slag met DevOpsDe ‘zachte’ kant belicht

AAN DE SLAG MET DEVOPS

Hoe creëer je zo’n cultuur? Door er zelf mee te beginnen. Door aan andere mensen te laten zien dat je wilt begrijpen wat zij aan het doen zijn. Begin zelf met het delen van kennis door bijvoorbeeld naast iemand te gaan zitten als hij zijn werk doet. Neem de tijd om de ander te begrijpen, en te horen wat er voor hem belangrijk is. Denk hierbij juist ook aan de mensen die niet in je team zitten. Hiermee laat je zien dat er wederzijds respect is en ook voor elkaars kennis en kunde.Een tweede stap is jezelf verantwoordelijk maken voor de kwaliteit van je werk. Deze moet van dusdanig hoog niveau zijn dat iemand die niet jouw vakkennis heeft met gemak kan begrijpen wat je doet. Las bij-voorbeeld een pair programmingsessie in en gebruik de feedback die de ander geeft. Alles wat hij of zij niet begrijpt aan jouw code is im-mers directe feedback op de kwaliteit ervan. Door jezelf open te stellen voor de kritiek van anderen wordt je code beter. Als je anderen kritisch naar jouw werk laat kijken, dan laat je daarmee zien dat je openstaat voor snelle feedback.Op basis van het nieuwe vertrouwen kun je effectief samenwerken over bestaande dis-ciplines heen. Gebruik de synergie tussen de mensen om het proces te verbeteren. Identi-ficeer de huidige belemmeringen in de diverse werkwijzen. Werk samen aan het wegnemen ervan en optimaliseer zo je werkproces. Wan-neer de organisatie merkt dat er procesverbe-teringen zijn, zal de rest snel volgen.

Welke businesscase bestaat er voor DevOps?Er bestaat een gezonde businesscase om met DevOps aan de slag te gaan, maar deze is niet direct duidelijk als je naar de traditionele werkvloer kijkt. Het denken in functionele teams leidt tot een focus op het uitvoeren van de eigen taak in plaats van het toevoegen van waarde voor de klant. De businesscase ligt in het creëren van synergie door middel van multidisciplinaire teams. Het succes van Scrum heeft aangetoond dat samenwerken met andere partijen loont. DevOps gaat een stap verder door develop-ment en operations in een team te verenigen. De verbintenis tussen development en opera-tions levert zowel op korte als lange termijn de volgende voordelen op:1. Teamspelers leveren betere kwaliteit.

Mensen die samenwerken, bereiken meer en krijgen meer gedaan in kortere tijd.

2. Door het automatiseren van ons eigen werk kunnen we sneller en goedkoper le-

veren. We zijn immers automatiseerders en dat is waar we goed in zijn.

3. Een aanzienlijke kostenbesparing door het elimineren van wachttijden. Vanuit de Lean- gedachte is wachten pure verspilling.

Door het introduceren van een relatie tus-sen development en operations kunnen we nieuwe elementen in ons softwareleverings-proces optimaliseren. Er bestaat in feite een wederzijdse afhankelijkheid. Je kunt niet meer zonder elkaar!

Hoe gaan ontwikkelaars en beheerders samenwerken?Cruciaal bij samenwerking is een gezamenlijk doel. Dus het eerste wat je doet als je gaat sa-menwerken is een doel stellen. Dat doel moet verbindend en herkenbaar zijn, en je als team in staat stellen om continu te verbeteren. Van daaruit komt vanzelf de behoefte om bij elkaar te gaan zitten. Je hebt elkaar immers nodig om dat doel na te streven.Om succesvol samen te werken, is wederzijds begrip van waar ons werk uit bestaat essen-tieel. Zie het als jouw verantwoordelijkheid om aan de ander uit te leggen waar je werk uit bestaat. Neem de tijd om naar elkaar te luisteren. Je moet weten waar je als team mee bezig bent en waarom je bepaalde taken al dan niet uitvoert. Nu we weten wat ons doel is en waar ons werk uit bestaat, richten we ons op het maxi-maal faciliteren van elkaar om ons doel te bereiken. En dat betekent dat je soms taken moet oppakken die niet in je traditionele ta-kenpakket zitten. In een DevOps-team moet je dus af en toe uit je comfortzone komen. Maar doe dat in het teambelang. Waarom is geautomatiseerd en vaak deployen naar productie veiliger?Als je de keuze hebt tussen geautomatiseerd en vaak deployen naar productie of handma-tig en weinig deployen naar productie, dan is

OM SUCCES-VOL SAMEN TE WERKEN, IS WEDER-ZIJDS BEGRIP VAN WAAR ONS WERK UIT BESTAAT ESSENTIEEL.

Experience the commitment

CGI heeft vacatures door het hele land. Kijk op www.werkenbijcgi.nl voor de verschillende mogelijkheden. Lees meer op blz. 39.

Jij weet wat Java kan.Maar weet Java al wat jij kan?

Advertentie

DevOps.indd 13 5/1/13 2:36 PM

Page 14: Java Magazine #1 - 2013

14

JAVA MAGAZINE

de eerste optie veiliger. Handmatige releases naar productie zijn vaak risicovolle onderne-mingen. Er zijn allerlei dingen die fout kunnen gaan en vaak gaat er ook iets mis. De mense-lijke factor speelt bij het maken van fouten een significante rol. In cruciale omgevingen wordt deze factor verwijzingen dan ook inge-schat en geanalyseerd.DevOps stelt om deze reden dat het een goed idee is om geautomatiseerd te deployen. Bij een geautomatiseerde deployment zorgt de programmatuur ervoor dat de deployment keer op keer op dezelfde wijze wordt uitge-voerd. Dit haalt menselijke fouten weg bij de uiteindelijke release naar productie. Daar-naast is het bij geautomatiseerde releases naar verschillende omgevingen triviaal om exact dezelfde stappen uit te voeren. Daar-door kun je gemakkelijker nieuwe omgevingen inrichten en opschalen.Wanneer we al onze deployments geauto-matiseerd doen, ontstaat de neiging om vaker releases te willen doen. Het is in een geautomatiseerde omgeving gemakkelijk om een deployment te doen, omdat je deze alleen maar hoeft te starten. Als we kleinere changes releasen, is de kans minder groot dat een change een groot risico met zich mee brengt (Figuur 2).Geautomatiseerd en vaak deployen naar productie is dus veiliger. Toch moeten we als professionals rekening houden met het feit dat mensen van nature weerstand hebben tegen verandering. Gebruik die weerstand als informatie over hoe zij de verandering beschouwen. Hieronder twee voorbeelden van weerstand die we in de praktijk zijn tegengekomen en hoe we daarmee zijn omgegaan:

Er is niemand die kan besluiten of een change wel of niet door mag.< Probeer samen te achterhalen op basis

waarvan de besluitnemer dit besluit zou nemen en automatiseer dat beslissings-proces. Zorg ervoor dat het beslissingspro-ces actueel blijft en wordt bijgehouden. De besluitnemer kan in zijn nieuwe rol het beslissingsproces steeds beter maken.

Wat als er een fout in de code zit en die wordt uitgerold in productie?< Code zit altijd vol met fouten. De vraag is

of wij (of de klant) die fouten detecteren. Als we fouten in het normale proces met een test hebben opgespoord, dan voegen we die test toe aan onze testsuite en vin-den wij ze ook.

< Programmeerfouten worden continue in productie gezet. Het is één van de grote redenen dat we beheer nodig hebben. Het loont dan ook de moeite om jezelf af te vragen, of je liever drie maanden of één uur wilt wachten tot de fout is gefikst.

Realiseer jezelf dat je andere mensen nooit kunt dwingen iets te doen. Wanneer zij weerstand hebben, dan wacht er een taak op je. Neem deze taak serieus en probeer hen te begeleiden in het veranderingsproces. Probeer ervoor te zorgen dat de ander de voordelen van de verandering inziet, maar dat jij ook begrijpt wat hem ervan weerhoudt jouw enthousiasme te delen. Onthoud wat de voordelen zijn van geautomatiseerd en vaak deployen naar productie. Deployments worden voortaan zonder menselijke fouten uitgevoerd en door kleinere changes zijn ze minder risicovol.

Figuur 2: Risico bij weinig en veel releases

PROBEER ERVOOR TE ZORGEN DAT DE ANDER DE VOORDELEN VAN DE VER-ANDERING INZIET, MAAR DAT JIJ OOK BEGRIJPT WAT HEM ERVAN WEERHOUDT JOUW EN-THOUSIASME TE DELEN.

DevOps.indd 14 5/1/13 2:37 PM

Page 15: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

AAN DE SLAG MET DEVOPS

Hoe kun je met DevOps laten zien dat je succesvol bent?Succes is een woord dat voor ieder mens een andere betekenis heeft. Met succes bedoelen we hier: het door het team vaststellen van doelen en ze gezamenlijk bereiken. Een doel is hier een meetbare verbetering met betrek-king tot de manier waarop de software draait in productie. Om goed doelen te kunnen stellen, hebben we eerst informatie nodig. We moeten weten wat er gebeurt in de productie-omgeving. Om informatie te verkrij-gen, moet het team gemakkelijk data kunnen terugkrijgen van de produc-tiemachine over wat er daadwerkelijk gebeurt. Zorg er daarom voor dat je zoveel mogelijk productiestatistieken gaat bijhouden. Gebruik hiervoor een oplossing waarmee je gemakkelijk een nieuwe statistiek kunt bijhouden. Handige tools hierbij zijn bijvoorbeeld StatsD en Graphite.Een dashboard is een visuele weergave van alle statistieken die je bijhoudt in de produc-tieomgeving. Iedereen mag het dashboard zien en ieder teamlid kan een voorstel doen om er nog een statistiek aan toe te voegen. Door een goede duidelijke weergave van je dashboard, is het voor iedereen visueel inzich-telijk of je doelstellingen daadwerkelijk zijn behaald. Het dashboard vergroot het vertrou-wen in de werking van de applicatie en maakt direct inzichtelijk als er iets aan de hand is in productie. Zo kun je problemen zo snel moge-lijk detecteren en oplossen. Denk daarbij niet alleen aan technische aspecten, maar ook aan bijvoorbeeld het aantal misclicks of end-of-session-handelingen door gebruikers.Het dashboard heb je nodig voor het stellen van doelen en om inzichtelijk te maken dat je ze behaalt. Zorg daarom voor een snelle implementatie van het dashboard bij het De-vOps- implementatietraject. Definieer doelen aan de hand van het dashboard en laat aan iedereen zien dat je doelen bereikt worden. Dan ziet iedereen dat je succesvol bent.

ConclusieDevOps is een logisch vervolg op het Agile-gedachtegoed. Het helpt organisaties om sneller, beter en gecontroleerd software te releasen. Het is essentieel dat je collega’s de DevOps-gedachte ondersteunen. Door mensen te verbinden, een gezamenlijk doel te stellen en processen af te stemmen op de samenwerking, ontstaat er vanzelf een sfeer, waarin je als team maximaal gebruikmaakt

VERWIJZINGEN1. http://agilemanifesto.org/principles.html2. Wilson, J.R. (1993). SHEAN (Simplified Human Error Analysis code) and auto-

mated THERP. United States Department of Energy Technical Report Number WINCO--11908.

3. http://dhemery.com/articles/resistance_as_a_resource/

Ben jij ook eenChampions League speler?

Kijk voor onze vacatures op pagina 20/21 van dit magazine.

Advertentie

van elkaars kennis en kunde. Wij hebben dit zelf succesvol gedaan en gunnen jou dit ook. Wij hopen dat we een tipje van de sluier heb-ben opgelicht en dat ook jij je organisatie wilt gaan verbeteren met DevOps.

DevOps.indd 15 5/1/13 2:37 PM

Page 16: Java Magazine #1 - 2013

16

JAVA MAGAZINE

Effectieve EAI met Apache CamelVeranderende requirements en integratie behoeften

Requirements in IT-projecten zijn gevoelig voor verandering, en dat geldt ook voor re-quirements aan de integratie met andere systemen. In staat zijn om snel te reageren op deze veranderingen kan cruciaal zijn voor een succesvol project. Gelukkig biedt Enterprise Application Integration (EAI) ons alle kennis, technologie en best practices om uitbreid-bare, onderhoudbare integratie oplossingen te bouwen op een productieve manier.

De meeste integratie oplossingen stellen ons echter wel voor een dilemma: terwijl ze vol met mogelijkheden zitten en heel geschikt zijn voor complexe projecten en een veeleisende omgeving, vereisen zij ook grote investerin-gen vooraf als het gaat om het leren van het systeem en het onderhouden ervan. Om deze reden lijken ad-hoc oplossingen erg aantrek-kelijk op het moment dat onze integratie eisen simpel zijn. Maar ze worden moeilijk te onderhouden en contraproductief indien de integratie behoeften groeien. Het toepassen van EAI best practices zou ons in staat kunnen stellen om een ad-hoc oplossing gaandeweg te laten groeien, maar dit vergt op zichzelf ook inspanning en kennis. Hoe kunnen we dan productief zijn wanneer wij worden gecon-fronteerd met zowel eenvoudige als complexe integratie problemen, terwijl we grote inves-teringen vooraf vermijden? In dit artikel zal ik betogen dat Apache Camel een oplossing biedt. Ik zal laten zien dat Camel kan voldoen aan complexe integratie vraagstukken maar ook gemakkelijk is op te pakken en gemakke-lijk te beheersen.

Bescheiden begin Integratie begint vaak simpel. Zoals het ophalen van een bestand vanaf een FTP server om het lokaal op te slaan. In dit stadium lijkt de doe-het-zelf oplossing erg aantrekkelijk. Maar laten we dat eens nader bekijken. Deze oplossing zou er als volgt uit kunnen zien: Deze oplossing maakt gebruik van de FT-PClient klasse van Apache Commons. Omdat

public class FTPFetch

public static void main(String[] args) FTPClient ftp = new FTPClient(); try ftp.connect(“host”); //probeer te verbinden

if (!ftp.login(“camel”, “apache”)) //log in op de server ftp.disconnect(); return;

int reply = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) ftp.logout(); ftp.disconnect(); return;

ftp.changeWorkingDirectory(“folder”);

//maak een stream aan naar het bestemmingsbestand file.xml OutputStream output = new FileOutputStream(“data/outbox/file.xml”); ftp.retrieveFile(“file.xml”, output); //doe de data overdracht output.close(); ftp.logout(); ftp.disconnect();

catch (Exception ex) ex.printStackTrace();

finally if (ftp.isConnected()) try ftp.disconnect(); catch (IOException ioException) ioException.printStackTrace();

EAI met Apache Camel.indd 16 5/1/13 2:43 PM

Page 17: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

Effectieve EAI met Apache CamelVeranderende requirements en integratie behoeften

het maar een client is en niets meer, moeten we het opzetten van een FTP verbinding en foutafhandeling zelf regelen. Maar wat als het bestand op de FTP server later verandert? Om dergelijke veranderingen te kunnen detecteren zouden we dan zelf code moeten schrijven om bijvoorbeeld dit bestand periodiek binnen te halen. Laten we nu eens kijken naar Apache Camel. Camel is een framework voor applicatie inte-gratie en ontworpen om dit soort problemen op te lossen door het volgen van EAI best practices. Camel kan worden gezien als een gereedschapskist van kant en klare integratie componenten. Maar het is ook een runtime die voor specifieke behoeften kan worden aan-gepast door deze componenten aan te vullen en te combineren. Dit is hoe we het probleem hierboven zouden oplossen met Camel:

Let op de from en to methoden. Camel noemt dit een ‘route’: het pad dat wordt doorlopen door de gegevens vanaf de bron naar de bestemming. Bericht bronnen en bestem-mingen worden ‘endpoints’ genoemd, en het is door hen dat Camel data ontvangt en verzendt. Endpoints worden opgegeven met een URI geformatteerde string zoals te zien in de argumenten voor de from en to methoden. Op deze manier worden de routes declaratief aangemaakt en geregistreerd bij Camel, die deze informatie gebruikt om runtime te weten wat het moet doen. De rest is enkel boilerplate code die wordt hergebruikt als meer routes worden toege-voegd en is veel eenvoudiger dan rechtstreeks babbelen met een FTP server. Camel zal ook

zorg dragen voor de lastige FTP details en zal zelfs het periodiek benaderen van de server voor zijn rekening nemen voor het geval het bestand verandert, aangezien we Camel heb-ben geconfigureerd om voor onbepaalde tijd te blijven draaien in de laatste regel. De from en to methoden zijn onderdeel van de Camel DSL, een Domain Specific Language waarvan het ‘domein’ EAI is. Dat betekent dat in tegenstel-ling tot andere oplossingen er geen vertaling hoeft te worden gemaakt tussen de EAI taal en de Camel taal: beide zijn vrijwel gelijk. Dit helpt om de leercurve te beperken en het instappunt laag te houden. Dus als je eenmaal je probleem in EAI termen hebt doorgrond, is het een relatief kleine stap om het uit te voe-ren met Camel. Het resultaat is compacte en effectieve code. Maar de code die je schrijft is niet het enige dat compact is: alles wat nodig is om dit draaiende te krijgen is camel-core.jar en camel-ftp.jar (plus afhankelijkheden), samen slechts een paar MB. De main klasse CamelRunner kan dan worden uitgevoerd vanaf de commandline. Dus hoewel je Camel prima kunt uitrollen in een volwaardig J2EE application server zoals JBoss, word je er niet toe gedwongen. Je doet het dus wanneer het jou uitkomt, niet omdat het van je EAI vendor moet. Dus het kiezen van een doe-het-zelf-oplossing om de enkele reden dat frameworks veel complexiteit toevoegen is niet geldig: Camel is eenvoudig te begrijpen, eenvoudig te gebruiken en eenvoudig uit te rollen.

Vertrouwen op CamelWe hebben net kunnen zien dat Camel weinig reden overlaat om op een doe-het-zelf manier integratie problemen aan te pakken. Om dit punt te maken is echter een erg simpel probleem behandeld. De vraag is dan wel of Camel nog steeds een geschikte keuze is voor complexere situaties. Moeten we dan alsnog een van de zwaardere concurrenten kiezen? Dat is mijns inziens niet nodig. Met zijn uit-gebreide ondersteuning voor allerlei transport mechanismen zoals JMS, HTTP, SMTP, en nog veel meer is het mogelijk om met een veelheid aan systemen te koppelen. Integratie vraagstukken met complexe logica zijn met de Camel DSL op doeltreffende wijze op te lossen, omdat de DSL nauw aansluit op het integratie domein. Camel kent ook voorzienin-gen voor zelfgemaakte uitbreidingen, zodat je als ontwikkelaar de zaak in eigen hand kan ne-men mochten de standaard Camel bouwste-nen niet toereikend zijn. Bijzonder aan Camel is ook de ondersteuning voor het maken van unittests, tegenwoordig een onmisbaar wapen

public class CamelRunner public static void main(String args[]) throws Exception Main camelMain = new Main(); camelMain.enableHangupSupport(); //ctrl-c shutdown camelMain.addRouteBuilder(new RouteBuilder() public void confi gure()

from(“ftp://host/folder?username=camel&password=apache&fi leName=fi le.xml&delay=360000” ) .to(“fi le:data/outbox”);

);

camelMain.run(); //Camel blijft onbeperkt draaien

‘Frans van der Lek is een software engineer bij Capgemini met ervaring in web, mobile en EAI oplossingen. Als hij niet bezig is software te maken of te bedenken brengt hij graag zijn tijd door met zijn gezin, een goed boek of een lekkere kop koffie.’

EAI MET APACHE CAMEL

EAI met Apache Camel.indd 17 5/1/13 2:43 PM

Page 18: Java Magazine #1 - 2013

18

JAVA MAGAZINE

in het arsenaal van iedere ontwikkelaar. De vorige paragraaf heeft een aantal manieren geschetst waarmee Camel ons helpt complexi-teit van welk omvang ook het hoofd te bieden. Een EAI systeem kan echter voor uitdagingen van een compleet andere aard komen te staan, en ook aan die uitdagingen willen we kunnen voldoen. Om die te begrijpen moeten we echter een stapje terug doen zodat we het geheel waarin Camel opereert in ogenschouw kunnen nemen. Een belangrijk kenmerk van integratie oplossingen is het feit dat ze een tussenstation vormen tussen systemen. Daarmee is het echter zelf een single point of failure. En naarmate meer en meer systemen onderling verbonden worden door middel van het centrale EAI systeem zullen storingen, gegevensverlies en performance daling steeds minder aanvaardbaar worden (voor zover ze het al waren). En dat terwijl het volume aan data alleen maar toeneemt. Camel kan niet op zichzelf dergelijke eisen volledig adresse-ren, daar is het simpelweg niet voor gemaakt. Camel is echter wel een centraal onderdeel in een dergelijke oplossing, want het bevat alle logica voor het verplaatsen van gegevens en het verbinden van alle andere systemen. Het is dus belangrijk om te weten dat Camel zijn taken kan blijven vervullen, ook in deze veeleisende omstandigheden. Laten we een concreet voorbeeld bekijken om te zien hoe aan zulke eisen doorgaans wordt voldaan. In dit voorbeeld is er een inkomende JMS queue waar berichten worden geplaatst door externe systemen. Camels taak zal zijn om de berichten op te pakken, te verwerken, en ze vervolgens te plaatsen in een uitgaande JMS queue. Laten we er vanuit gaan dat de verwerking vrij complex en rekenintensief zou kunnen zijn, maar voor de rest geheel op de node zelf plaatsvindt. JMS queues kennen hun eigen mechanismen om persistent te worden gemaakt en ‘high available’, wat betekent dat ze een hoge mate van beschikbaarheid heb-ben. Met dit gegeven gaan we ervan uit dat externe systemen ‘altijd’ berichten op de inko-mende queue kunnen plaatsen. Totdat het vol raakt natuurlijk, hetgeen zal gebeuren indien Camel de verwerking niet snel genoeg kan uitvoeren. Ons doel is dan om Camel bestand te maken tegen systeem storingen zodat het ook high available wordt, en de prestaties te verhogen. Dat doen we door het inzetten van meerdere servers (nodes), die elk een eigen Camel instantie runnen die aangesloten is op dezelfde eindpunten. Zie ook de afbeelding hiernaast.Dit heeft twee consequenties: ten eerste wor-

den de berichten uit de queue door meerdere Camel instanties opgepakt en parallel ver-werkt, zodat het systeem sneller wordt. Een bericht dat door een instantie wordt verwerkt is niet langer beschikbaar voor de anderen. Be-richten worden dus slechts eenmaal verwerkt. Ten tweede wordt het werk van een eventueel uitgevallen node automatisch overgenomen door de andere, nog draaiende nodes. De werk-last wordt bovendien verdeeld over de nodes die berichten oppakken: snellere nodes kun-nen berichten in een hoger tempo verwerken en nemen daarmee vanzelf meer werk voor hun rekening dan langzame nodes. Op deze manier wordt de coördinatie bereikt die nodig is om de verwerking van alle berichten correct en efficiënt te laten verlopen. Er is echter een element dat ontbreekt: mocht er namelijk een node uitvallen tijdens het verwerken van een bericht, dan moet een andere die verwerking overnemen want anders gaat dat bericht verloren. En mochten alle nodes uitvallen, dan moeten berichten die op dat moment in verwerking zijn ook niet verloren gaan. Om dat te kunnen bereiken maken we gebruik van transacties. Met transacties zal de JMS queue wachten op een bevestiging van de node die het bericht opnam alvorens het echt weg te gooien. Mocht de node uitvallen tijdens de verwerking dan komt die bevestiging nooit, en uiteindelijk zal er een rollback van de transac-tie plaatsvinden waardoor het bericht opnieuw terugkomt in de queue en weer beschikbaar zal zijn voor de nodes die nog wel actief zijn. Als er geen nodes actief zijn, blijft het bericht gewoon daar tot er een node uiteindelijk weer in de lucht komt. Voor Camel betekent dit dat de routes transactioneel moeten worden gemaakt zodat ze mee kunnen doen in een transactie. Camel heeft op zichzelf geen

IK RAAD IEDEREEN AAN DIE EEN EFFECTIEVE EN FLEXIBELE INTEGRATIE OPLOSSING ZOEKT OM ZICH WAT VERDER IN CAMEL TE VERDIEPEN.

EAI met Apache Camel.indd 18 5/1/13 2:43 PM

Page 19: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

EAI MET APACHE CAMEL

<beans //namespace declaraties verwijderd > //connectie naar jms server opzetten <jee:jndi-lookup id=”jmsConnectionFactory” jndi-name=”ConnectionFactory”> <jee:environment> java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory java.naming.factory.url.pkgs=org.jboss.naming.client java.naming.provider.url=jnp://localhost:1099 </jee:environment> </jee:jndi-lookup> //configuratie voor de transactionele jms client <bean id=”jmsConfig” class=”org.apache.camel.component.jms.JmsConfiguration”> <property name=”connectionFactory” ref=”jmsConnectionFactory”/> <property name=”transactionManager” ref=”jmsTransactionManager”/> <property name=”transacted” value=”true”/> <property name=”acknowledgementModeName” value=”TRANSACTED”/> <property name=”cacheLevelName” value=”CACHE_NONE”/> <property name=”transactionTimeout” value=”5”/> </bean> //registreer camel jms component bean <bean id=”jboss” class=”org.apache.camel.component.jms.JmsComponent”> <property name=”configuration” ref=”jmsConfig” /> </bean> //registreer spring transactionmanager bean <bean id=”jmsTransactionManager” class=”org.springframework.jms.connection.JmsTransactionManager”> <property name=”connectionFactory” ref=”jmsConnectionFactory”/> </bean> <camelContext xmlns=”http://camel.apache.org/schema/spring”> <route> <from uri=”jboss:queue:incoming”/> <transacted/> <log loggingLevel=”INFO” message=”processing started.” /> <!— tijdrovende verwerking hier --> <to uri=”jboss:queue:outgoing?exchangePattern=InOnly” /> </route> </camelContext></beans>

ondersteuning voor transacties, maar in plaats daarvan maakt het gebruik van 3rd party oplossingen. Dat houdt Camel eenvoudig, terwijl gebruik kan worden gemaakt van bewezen tech-nologieën terwijl het wisselen van im-plementaties wordt vergemakkelijkt. Als voorbeeld zullen we nu Camel met transacties configureren binnen een Spring container, zodat we de Spring JmsTransactionManager kunnen gebruiken. Merk op dat aangezien we binnen Spring draaien, het praktischer is om de Spring XML versie van de Camel DSL te gebruiken in plaats van de Java versie, ook al is dat laatste is ideaal voor beginners. De Camel DSL bestaat in meerdere varianten, niet alleen Spring/Java maar bijvoorbeeld ook Scala of Groovy. Nou betekent het veranderen van DSL’s tijdens een project uiteraard rework, dus is het belangrijk om te migreren op een geschikt moment. Gelukkig draait de Spring DSL ook in een unittest, zodat

unittests kunnen helpen om veilig de overgang te maken want ze zullen werken op routes ongeacht welk DSL type werd gebruikt.Met de <transacted/> tag wordt de route gemarkeerd als transactio-neel, zodat Camel alle stappen van die route binnen een transactie zal uitvoeren. Dat zorgt ervoor dat in het geval van een storing tijdens de verwerking van deze route er een rol-lback van de transactie plaatsvindt en dat het bericht dus terug komt in de inkomende berichten queue.

Conclusie Apache Camel heeft een gemakke-lijke leercurve en is licht in gebruik en uitrol zodat investeringen vooraf klein zijn. Zelfs in vrij eenvoudige geval-len kan het gebruiken van Camel een snellere weg naar integratie zijn dan doe-het-zelf oplossingen. Camel biedt dus zonder meer laagdrempelige toegang tot de best practices van EAI.

Maar Camel is ook prima inzetbaar in meer veeleisende omgevingen, bijvoorbeeld als onderdeel van een oplossing met hoge eisen ten aanzien van beschikbaarheid. Over het geheel genomen is Camel een uitstekende optie voor integratie van vrijwel elke omvang en complexi-teit: je kunt klein en eenvoudig begin-nen met een minimale investering vooraf in de wetenschap dat mochten integratie behoeften complexer wor-den, Camel je niet teleur zal stellen. In de tussentijd kun je productief blijven, terwijl je de vruchten plukt van een volwaardig integratie framework.In dit artikel hebben we maar een paar kanten van Camel kunnen be-lichten, er is nog veel meer dat Camel bijzonder en de moeite waard maakt zoals de DSL en unittest support. Ik raad dan ook iedereen aan die een effectieve en flexibele integratie oplossing zoekt om zich wat verder in Camel te verdiepen.

EAI met Apache Camel.indd 19 5/1/13 2:44 PM

Page 20: Java Magazine #1 - 2013

Bekijk dan de volgende vacatures• Junior en Senior Java Software Developer • Java Integratie Specialist• Java Solution Architect• Open Source Developer• Open Source Architect

Meer informatie kijk op www.werkenbijcapgemini.nl

of neem contact op met:Kees Heerschap Recruitment ManagerTel. 31 6 4609 3926 I E-mail: [email protected]

Ben jij ook eenChampions League speler?

03-021.13a_Advertisement_JavaMagazine_420x275_v1_220413.indd 1 4/24/2013 12:36:55 PMUntitled-1 2 29-4-2013 10:09:36

Page 21: Java Magazine #1 - 2013

Bekijk dan de volgende vacatures• Junior en Senior Java Software Developer • Java Integratie Specialist• Java Solution Architect• Open Source Developer• Open Source Architect

Meer informatie kijk op www.werkenbijcapgemini.nl

of neem contact op met:Kees Heerschap Recruitment ManagerTel. 31 6 4609 3926 I E-mail: [email protected]

Ben jij ook eenChampions League speler?

03-021.13a_Advertisement_JavaMagazine_420x275_v1_220413.indd 1 4/24/2013 12:36:55 PMUntitled-1 3 29-4-2013 10:09:36

Page 22: Java Magazine #1 - 2013

22

JAVA MAGAZINE

We kennen allemaal het aloude relationele model, dat door veel productleveranciers is geïmplementeerd in een Relationeel DataBase Management System (RDBMS). Denk bijvoor-beeld aan de relationele databases van Oracle, Microsoft en IBM. Rond het jaar 2000 was er veel behoefte aan salesreporting, marketingin-formatie etc. en waren de zogenaamde On Line Analytical Processing (OLAP) datawarehouses populair. Data werd op een andere manier gemodelleerd (stermodellen met dimensions en facts) en het redundant opslaan van data was toegestaan. Vanaf 2010 zijn NoSQL-databases steeds populairder geworden, wat niet betekent dat relationele databases en datawarehouses gaan verdwijnen. Ze zullen naast elkaar blijven bestaan. NoSQL database implementaties maken onder andere gebruik van andere vormen van opslag dan het klas-sieke relationele model. NoSQL databases zijn er in diverse verschij-ningen, en in veel gevallen doen ze iets wat met relationele databases minder goed kan. Een van de meest populaire databases van de laatste tijd is MongoDB. We zullen in dit artikel verder op deze database ingaan. Wat maakt MongoDB interessant en wat betekent deze ontwikkeling voor de Java ontwikkelaar?

MongoDB en 10genMongoDB is een open source document oriented database geschreven in C++. De data is opgeslagen als binairy JSON ook bekend als BSON. De eerste release is uitgebracht in 2009 en momenteel heeft v2.4 de pro-ductionele status. De database kan gemak-kelijk gedistribueerd worden. De data wordt

dan over meerdere computers verspreid om gedistribueerde gegevensverwerking mogelijk te maken. Er is geen ondersteuning voor joins en ondersteuning voor transacties is beperkt. MongoDB is beter geschikt voor Big Data dan een relationele database van Oracle, MySQL of Microsoft. Enkele belangrijke productionele omgevingen zijn Foursquare, bit.ly en CERN voor het verzamelen van grote hoeveelheden data. De belangrijkste features op een rij:

< Document data model with dynamic schemas

< Full, flexible index support and rich queries

< Auto-Sharding for horizontal scalability

< Built-in replication for high availability

< Text search< Advanced security< Aggregation Framework and MapReduce< Large media storage with GridFS

10gen is het bedrijf achter MongoDB en bege-leidt de MongoDB ontwikkeling, ondersteunt de grote en groeiende MongoDB community, biedt commerciële abonnementen inclusief ondersteuning, advies en training. Daarnaast biedt 10gen het gratis, cloud-gebaseerde MongoDB Monitoring Service (MMS).

Installeren van MongoDBJe kan MongoDB installeren op verschillende platformen, op zowel 32 bits als 64 bits archi-tecturen. Zie voor meer informatie op http://docs.mongodb.org/manual/installation/

MongoDB, de database van de toekomst?De evolutie van databases

Big Data is al lang geen hype meer. Data groeit niet alleen wat betreft hoeveelheid, ook de structuur van opslaan verandert. Omdat de hoeveelheid data toeneemt, wordt cloud compu-ting steeds vaker ingezet. Daarnaast moet data vanuit elke business geanalyseerd worden en het liefst realtime beschikbaar zijn. Bijvoorbeeld op dashboards op je eigen device (BYOD) zodat beleid eventueel snel kan worden aangepast.

Maikel Alderhout is Solution Architect bij VX Company en organizer van de Dutch MongoDB User Group (www.dutchmug.org)

MongoDB.indd 22 5/1/13 2:45 PM

Page 23: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

MONGODB

CRUD CV DatabaseWe maken een simple CV database aan, waar we perso-nen en expertisegroepen via CRUD functionaliteit kunnen beheren. Log aan in de MongoDB shell met “./mongo”

> use cvswitched to db cv

InsertOp het moment van een insert, is de database CV ook echt aangemaakt:

> db.person.insert( “name” : “Bas”, “group” : [ “Open Source”, “mongoDB”, “Big Data” ], )

en nog 1 toevoegen:

> db.person.insert( “name” : “Maikel”, “group” : [ “Oracle”, “ExaData”, “Big Data”], )

In MongoDB wordt “person” een collectie genoemd, en de rijen worden documents genoemd. We kunnen nu het aantal documents tellen:

> db.person.count()2

RetrieveMet behulp van het find commando kunnen we het docu-ment opvragen:

> db.person.find() “_id” : ObjectId(“5145adfcd6edf3d8f2d67108”), “name” : “Bas”, “group” : [ “Open Source”, “mongoDB”, “Big Data” ] “_id” : ObjectId(“5145ae14d6edf3d8f2d67109”), “name” : “Maikel”, “group” : [ “Oracle”, “ExaData”, “Big Data” ]

Wat nu opvalt is het veld “_id” van het type ObjectId. Een Objectid is een 12-byte BSON type, deze fungeert als pri-maire sleutel en is opgebouwd uit:een 4-byte tijdstempel, een 3-byte machine-id, een 2-byte proces-ID eneen 3-byte teller, die gevuld wordt met een willekeurige waarde.We kunnen nu ook documenten selectief selecteren. Geef alle documenten met een groep “Oracle”.

> db.person.find(“group” : “Oracle” ) “_id” : ObjectId(“5145ae14d6edf3d8f2d67109”), “name” : “Maikel”, “group” : [ “Oracle”, “ExaData”, “Big Data” ]

UpdateStel we besluiten het veld “group” te verwijderen bij het document met de naam “Maikel”

> db.person.update(name: “Maikel”, $unset: group: 1)> db.person.find() “_id” : ObjectId(“5145adfcd6edf3d8f2d67108”), “name” : “Bas”, “group” : [ “Open Source”, “mongoDB”, “Big Data” ] “_id” : ObjectId(“5145ae14d6edf3d8f2d67109”), “name” : “Maikel”

Of we vervangen alle group items bij het document met name “Bas”

> db.person.update(name: “Bas” , $set: “group” : [“EOSS”, “SQL”, “OpenStack”])> db.person.find() “_id” :

Of we voegen een group item “Oracle” toe, bij het document met de naam “Bas”

> db.person.update(name: “Bas” , $push: group: “Oracle” )> db.person.find() “_id” : ObjectId(“5145ae14d6edf3d8f2d67109”), “name” : “Maikel” “_id” : ObjectId(“5145adfcd6edf3d8f2d67108”), “group” : [ “EOSS”, “SQL”, “OpenStack”, “Oracle” ], “name” : “Bas”

UpsertEen upsert is een speciaal type update. Als er geen docu-ment wordt gevonden dat aan de update criteria voldoet, zal een nieuw document worden gecreëerd. Als er een overeenkomend document wordt gevonden, zal het op de normale manier worden ge-update. Voor het gebruik van Upsert voeg je de parameter “true” toe.

> db.person.update(name: “Jan” , $set: “group” : [“OpenStack”],true)> db.person.find() “_id” : ObjectId(“5145ae14d6edf3d8f2d67109”), “name” : “Maikel” “_id” : ObjectId(“5145adfcd6edf3d8f2d67108”), “group” : [ “EOSS”, “SQL”, “OpenStack”, “Oracle” ], “name” : “Bas” “_id” : ObjectId(“5145c1fbcb8282695dbab2af”), “group” : [ “OpenStack” ], “name” : “Jan”

MongoDB.indd 23 5/1/13 2:45 PM

Page 24: Java Magazine #1 - 2013

24

JAVA MAGAZINE

Multiple updateOok hier geldt het toevoegen van de parameter “true”.

> db.person.update( , $set: “group” : [“EOSS”, “mongoDB”, “OpenStack”], true, true )> db.person.find() “_id” : ObjectId(“5145ae14d6edf3d8f2d67109”), “group” : [ “EOSS”, “mongoDB”, “OpenStack” ], “name” : “Maikel” “_id” : ObjectId(“5145adfcd6edf3d8f2d67108”), “group” : [ “EOSS”, “mongoDB”, “OpenStack” ], “name” : “Bas” “_id” : ObjectId(“5145c1fbcb8282695dbab2af”), “group” : [ “EOSS”, “mongoDB”, “OpenStack” ], “name” : “Jan”

DeleteStel we willen het document met de naam “Maikel” verwijderen:

> db.person.remove(“name”: “Maikel”)> db.person.find() “_id” : ObjectId(“5145adfcd6edf3d8f2d67108”), “group” : [ “EOSS”, “mongoDB”, “OpenStack” ], “name” : “Bas” “_id” : ObjectId(“5145c1fbcb8282695dbab2af”), “group” : [ “EOSS”, “mongoDB”, “OpenStack” ], “name” : “Jan”

Stel we willen de hele collectie “person” verwijderen:

> db.person.drop()

ReplicatieReplicatie is zeer eenvoudig op te zetten met MongoDB. We gaan een primary (node1) en secundary (node2) instance aanmaken, met een aparte arbiter instance.

Een arbiter bepaalt de nieuwe primary in geval deze er niet meer is. Start met aanmaken van de data directories:

mkdir /data/node1mkdir /data/node2mkdir /data/arbiter

Start nu elke instance op in een aparte terminalsessie:

mongod --replSet person --dbpath /data/node1 --port 40001mongod --replSet person --dbpath /data/node2 --port 40002mongod --replSet person --dbpath /data/arbiter --port 40003

Log in op de primary instance om de replica set yet te confi-guren. Het eerste wat je ziet na het rs.initiate() commando is een foutmelding. RS staat voor replica set.

mongo localhost:40001MongoDB shell version: 2.2.3

connecting to: localhost:40001/test

> rs.initiate()“info2” : “no configuration explicitly specified -- making one”,“me” : “Computername.local:40001”,“info” : “Config now saved locally. Should come online in about a minute.”,“ok” : 1

Start nu de configuratie door de secundary en de arbiter te koppelen.

person:PRIMARY> rs.add(Computername:40002) “ok” : 1 person:PRIMARY> rs.add(Computername:40003, arbiterOnly:true) “ok” : 1

Kijk nu met behulp van het rs.status() commando. De primary, secundary en de arbiter zijn opgezet:

person:PRIMARY> rs.status() “set” : “person”, “date” : ISODate(“2012-10-28T19:50:52Z”), “myState” : 1, “members” : [ “_id” : 0, “name” : “Computername.local:40001”, “health” : 1, “state” : 1, “stateStr” : “PRIMARY”, “uptime” : 1266, “optime” : Timestamp(1351453811000, 1), “optimeDate” : ISODate(“2012-10-28T19:50:11Z”), “self” : true , “_id” : 1, “name” : “Computername.local:40002”, “health” : 1, “state” : 2, “stateStr” : “SECONDARY”, “uptime” : 41, “optime” : Timestamp(1351453811000, 1), “optimeDate” : ISODate(“2012-10-28T19:50:11Z”), “lastHeartbeat” : ISODate(“2012-10-28T19:50:51Z”), “pingMs” : 0v ],“ok” : 1 “_id” : 1, “name” : “Computername.local:40003”, “health” : 1,

App

Read/Write

Reads(Optional) Asynchronous

Replication

Reads(Optional)

Primary

Secundary

Secundary

MongoDB.indd 24 5/1/13 2:45 PM

Page 25: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

MONGODB

Vervolg code:

“state” : 3, “stateStr” : “ARBITER”, “uptime” : 14, “optime” : Timestamp(1351453811000, 1), “optimeDate” : ISODate(“2012-10-28T19:50:11Z”), “lastHeartbeat” : ISODate(“2012-10-28T19:50:51Z”), “pingMs” : 0 ], “ok” : 1

Het is nu tijd om een test te doen door middel van het toevoegen van een document in de primary instance:

person:PRIMARY> use cvswitched to db cvperson:PRIMARY> db.person.save(“name” : “Maikel”,“group” : [ “Oracle”, “ExaData”, “Big Data”], )

Log in op de secundary en gebruik nog wel het rs.slaveOk() command om aan te geven dat lezen mo-gelijk is. Test of de collection en het document ook hier bestaan:

mongo localhost:40002MongoDB shell version: 2.2.3connecting to: localhost:40002/testperson:SECONDARY> rs.slaveOk()person:SECONDARY> use cvswitched to db cvperson:SECONDARY> db.person.find() “_id” : ObjectId(“508d971dda0730903]bcbb612”), “name” : “Maikel”, “group” : [ “Oracle”, “ExaData”, “Big Data” ] person:SECONDARY>

We gaan nu een scriptje maken dat 1000000 documents (persons) genereert:

person:PRIMARY> for(i=0; i<1000000; i++) db.person.save(person: i);

Log aan op de secundary en check of de data ook hier binnenkomt:

person:SECONDARY> db.person.find() “_id” : ObjectId(“508f95e9e38917f43ae20db3”), “person” : 0 “_id” : ObjectId(“508f95e9e38917f43ae20db4”), “person” : 1 “_id” : ObjectId(“508f95e9e38917f43ae20db5”), “person” : 2 “_id” : ObjectId(“508f95e9e38917f43ae20db6”), “person” : 3 “_id” : ObjectId(“508f95e9e38917f43ae20db7”), “person” : 4 “_id” : ObjectId(“508f95e9e38917f43ae20db8”), “person” : 5 “_id” : ObjectId(“508f95e9e38917f

Vervolg code:

43ae20db9”), “person” : 6 “_id” : ObjectId(“508f95e9e38917f43ae20dba”), “person” : 7 “_id” : ObjectId(“508f95e9e38917f43ae20dbb”), “person” : 8 “_id” : ObjectId(“508f95e9e38917f43ae20dbc”), “person” : 9 “_id” : ObjectId(“508f95e9e38917f43ae20dbd”), “person” : 10 “_id” : ObjectId(“508f95e9e38917f43ae20dbe”), “person” : 11 “_id” : ObjectId(“508f95e9e38917f43ae20dbf”), “person” : 12 “_id” : ObjectId(“508f95e9e38917f43ae20dc0”), “person” : 13 “_id” : ObjectId(“508f95e9e38917f43ae20dc1”), “person” : 14 “_id” : ObjectId(“508f95e9e38917f43ae20dc2”), “person” : 15 “_id” : ObjectId(“508f95e9e38917f43ae20dc3”), “person” : 16 “_id” : ObjectId(“508f95e9e38917f43ae20dc4”), “person” : 17 “_id” : ObjectId(“508f95e9e38917f43ae20dc5”), “person” : 18 “_id” : ObjectId(“508f95e9e38917f43ae20dc6”), “person” : 19 Type “it” for more person:SECONDARY> db.person.count() 194079 person:SECONDARY> db.person.count() 215657 person:SECONDARY> db.person.count()

228488 person:SECONDARY> db.person.count() 239528 person:SECONDARY>

Het werkt!Download nu de nieuwste Java driver voor MongoDB van: https://github.com/mongodb/mongo-java-driver/downloads Maak een nieuw Java project aan in Eclipse of een andere IDE. Voeg de gedownloade JAR file toe in het build path. Gebruik de code op de volgende pagina om je main class op te zetten.

10gen is met MongoDB community gedreven, iedereen kan suggesties (tickets) inbrengen en volgen op: https://jira.mongodb.org/Voordelen MongoDB< MongoDB kan als generieke database worden

ingezet en is flexibel in te richten< MongoDB kan overweg met grote hoeveelheden

data: • hoog beschikbaar onder andere door middel van replicatie • horizontale schaalbaarheid onder andere door middel van sharding

< Flexibel modelleren (geen joins, maar nested values)

< Gemakkelijk in gebruik

MongoDB.indd 25 5/1/13 2:45 PM

Page 26: Java Magazine #1 - 2013

26

JAVA MAGAZINE

Na het starten krijg je de volgende output:

number of documents : 1000001 “group” : “Big Data” “_id” : “$oid” : “50904c1912644ddba9ec-6c1e” , “name” : “Maikel” , “group” : [ “Oracle” , “ExaData” , “Big Data”]

Nu is het tijd om de primary ins-tance te stoppen (Figuur 1). Check wat er gebeurt met de secondary (rs.status()). De arbiter kiest een nieuwe primary instance. Start het Java programma opnieuw. Als het goed is krijg je gewoon dezelfde output, zonder het Java programma

aan te passen (Figuur 2)! Als de oude primary weer in de lucht komt, start het recovery proces. De oude primary fungeert nu als nieuwe secondary. Ook nu zal de applicatie gewoon blijven werken!

MongoDB v2.4 featuresOp het moment van schrijven heeft v2.4 de productie status gekregen. Hieronder de belangrijkste features:Text search is een van de meest gevraagde functies voor MongoDB en 10gen werkt al een tijdje aan een experimentele tekst-zoekfunctie. Advies is wel om text search niet direct op de productieomgevingen te

package nl.nljug;import java.net.UnknownHostException;import java.util.ArrayList;import java.util.List;import com.mongodb.*; /** * Simple Person Report finding persons in a particular group. * */public class PersonReport /** * Find a persons which participating in a special interest group. * @param groupName * @param personCollection * @return cursor to persons found */public DBCursor getPersonWithGroup(String groupName, DBCollection personCollection) // Construct JSON with DBObjects DBObject fields = new BasicDBObject(“group”, groupName); // Show what we are doing... System.out.println(fields); // Sort on name (descent order) DBObject orderBy = new BasicDBObject(“name”, -1); // return persons which met the conditions return personCollection.find(fields).sort(orderBy); public static void main(String[] args) throws UnknownHostException // Application is aware of replicaset of mongoInstances List addr = new ArrayList(); addr.add(new ServerAddress(“127.0.0.1”, 40001)); addr.add(new ServerAddress(“127.0.0.1”, 40002)); addr.add(new ServerAddress(“127.0.0.1”, 40003)); // Connect to replica set Mongo mongo = new Mongo(addr); // Get the Person Collections from test database DBCollection collection = mongo.getDB(“test”).getCollection(“person”); // Just for the fun count number of documents in person collection System.out.println(“ number of documents : “ + collection.getCount()); PersonReport personReport = new PersonReport(); DBCursor cursor = personReport.getPersonWithGroup(“Big Data”, collection); // Loop through found persons... try while(cursor.hasNext()) System.out.println(cursor.next()); finally cursor.close();

Figuur 1

implementeren, maar eerst te probe-ren op testomgevingen. Google’s V8 zal Mozilla’s SpiderMon-key vervangen als de onderliggende JavaScript-engine. Hoewel er wellicht enkele voordelen behaald kunnen worden, kan er geen sprake zijn van opmerkelijke verschillen voor de meeste MongoDB gebruikers. Er zijn wel benchmarks uitgevoerd, waaruit blijkt dat het effect het grootste is in MongoDB omgevingen waar sharding (partitioning) is ingezet. Verder zijn er nog enkele nieuwe (Geospatial) indexen bijgekomen en is hash-based sharding geïntro-duceerd, om nog betrouwbaarder de data te distribueren over de verschillende shards. Daarnaast is er nu een modulair opgezet authenti-catie mechanisme met support voor Kerberos.

App

Primary

Secundary

Secundary

App

Recovering

Primary

Secundary

App

Secundary

Primary

Secundary

App

Primary

Secundary

Secundary

Automatic electionof new

Primary

Figuur 2

MongoDB.indd 26 5/1/13 2:45 PM

Page 27: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

Log4J 2.0Log4J is, ondanks dat het een echte klassieker is, waarschijnlijk de meest populaire library ooit. Dui-zenden applicaties gebruiken al vele jaren Log4J in het hart van hun systemen om kritische meldingen te loggen. Zal wel goed werken toch? Echte Log4J veteranen weten wel beter. Memory leaks, subtiele performance problemen, mysterieuze reacties als niet kan worden geschreven, een vaak verwarrende confi-guratie die runtime niet foutloos te wijzigen is. Log4J 2.0 (http://logging.apache.org/log4j/2.x/) heeft als doel om verbeteringen te adopteren uit het alterna-tieve framework Logback. Een moderne, prettige API, gestroomlijnde configuratie die runtime gewijzigd kan worden zonder logging events te verliezen, hoge performance en robuust gedrag bij schrijfproblemen. Momenteel nog in beta, maar zeker een aanrader om te volgen.

LIBRARIES UITGELICHT

Libraries uitgelicht

JavaParserWellicht kan iedereen zich de volgende situatie wel voor de geest halen, je moet een refactoring doorvoeren, maar je favoriete IDE biedt deze mogelijk niet of levert een hele berg aan compilatie fouten op, welke vervolgens handmatig moeten worden aangepast. Met behulp van JavaParser is het mogelijk om je eigen refactoring tools te schrijven, deze library zorgt voor het inlezen van de source code en vervolgens kun je over de AST lopen en deze aanpassen en vervolgens weer wegschrijven. In een aantal gevallen loont het zeker om op deze manier slim een refactoring uit te voeren, maar er zijn natuurlijk nog tal van andere toepassingen te bedenken voor deze kleine maar krachtige library. Voor meer informatie zie http://code.google.com/p/javaparser

De Java APIHet is voor sommigen een tweede natuur. Je hebt een bepaalde functionaliteit nodig voor je Java oplossing en via je zoekmachine vind je al snel een nieuwe library die je toevoegt aan je project. Veelal zit die functi-onaliteit in de standaard API van Java. Het is zeker waar dat sommige oplossingen omslachtige regels code vereisen en niet altijd evident zijn. Het is echter de vraag of dit de introductie van een nieuwe library rechtvaardigt of dat een eigen geschreven utility class voldoet. De kunst is deze verborgen juweeltjes in de Java API te vinden en handig toe te passen in jouw op-lossing. Misschien is dit toch een overweging voordat je op zoek gaat naar de zoveelste handige library van de benodigde functionaliteit.

JSefaJe wilt even een csv bestand inlezen en mappen naar een entiteit voor verdere verwerking. Daar zijn genoeg libraries voor, waarvan openCSV wel de bekendste is. Wat JSefa bijzonder maakt, is dat het een generieke java serializer voor XML, CSV en FLR op basis van JSR 173(Stax) is. Daarnaast kun je JSefa ook uitbreiden om eigen formaten te ondersteunen. Het mooie is dat je door middel van annotaties aangeeft, hoe en op welke velden de mapping moet plaatsvinden en dit voor de verschillende formaten. Ideaal om bijvoorbeeld een JPA entiteit te decoreren met csv en/of xml annota-ties . Daarna is serialisatie een kwestie van factory oproepen met een reader of writer en de geannoteerde klasse en gaan.

XMLUnitAls je veel met webservices werkt, komt het geregeld voor dat je voor test-cases stukken XML met elkaar wil vergelijken. Op het eerste oog lijkt dat een triviale klus, totdat je er ermee aan de slag gaat: je krijgt te maken met namespaces, al dan niet self closing elementen, niet exact te voorspellen waarden (zoals timestamps), noem maar op. XMLUnit biedt hierbij hulp met twee uitbreidingen op JUnit: XMLAssert en XMLTestCase. Hiermee kun je assertions maken voor:< overeenkomsten of verschillen tussen twee stukken XML;< het evalueren van XPath-expressies op een stuk XML;< het valideren van XML;< het resultaat van een XSL-transformatie van een stuk XML.Als kers op de taart kun je XMLUnit naast XML ook HTML laten verwerken, zodat je deze assertions ook kunt gebruiken bij tests van webpagina’s.

Libraries uitgelicht

LIBRARIES UITGELICHT

Libraries uitgelicht.indd 27 5/1/13 2:47 PM

Page 28: Java Magazine #1 - 2013

28

JAVA MAGAZINE

De Raspberry Pi is een computer ter grootte van een creditcard. Het is een vernuftig ap-paraatje met een robuust karakter en handige aansluitingen, dat tegen een schappelijke prijs online te bestellen is, waardoor het een uitstekend platform is om mee te experimen-teren. De Raspberry Pi is ontwikkeld, nadat werd geconstateerd dat de huidige generatie startende IT-studenten zelden met compu-ters experimenteert. Vaak komt dit omdat de ouders het niet zien zitten dat zoon- of dochterlief uit nieuwsgierigheid hun kostbare bezit uit elkaar schroeft. Sinds de introductie zijn het niet alleen ouders, kinderen en onderwijsinstellingen die een Raspberry Pi aanschaffen, maar vindt het computertje ook gretig aftrek bij hobbyisten. Dit leidt tot veel grappige, handige en crea-tieve toepassingen met een Raspberry Pi, met name op het gebied van home automation.In dit artikel bespreken we twee toepassingen van een Raspberry Pi met Java. In de eerste toepassing sturen we een aantal led’s aan via een website. Dit project staat model voor een softwarematige aansturing van hardware via

Mobiele enterprise-server Ja-Pi is de eerste

Marco Hebing, Remko de Jong, en Eelco Meuter van Ordina zijn gek van de Raspberry Pi en wilden wel eens kijken wat er mogelijk is. Zo zochten ze uit hoe je met Java enkele led’s via een website kunt aansturen. Daarnaast hebben ze een eigen mobiele Java enterpriseserver gebouwd.

de pinnen van de General Purpose Input Out-put (GPIO) met Java; oftewel de ‘hello world’ van de elektronica.Het tweede project is wat extremer: bouw je eigen mobiele Java enterpriseserver. In dit project installeren we een volwassen appli-catieserver op de Raspberry Pi en monteren deze op een robot. Het praktisch nut van deze mobiele applicatieserver is ons nog niet helemaal duidelijk, maar dat mag de pret niet drukken.De Raspberry Pi die we tijdens de projecten gebruiken, is van het type Model B (versie 2). Er zijn twee types op de markt. Het verschil tussen Model A en B is dat Model B een extra usb- en ethernetaansluiting heeft en 512 MB RAM, in plaats van de 256 MB die in een Model A zit. Verder draait onze Raspberry Pi met de standaard Linux-distributie en is tijdens de initiële configuratie overgeklokt naar 800 Mhz.

Led there be PiWe beginnen met het aansturen van enkele led’s via de GPIO-aansluiting (P1). Het bood-schappenlijstje in het kader vermeldt de onderdelen die je nodig hebt. De GPIO-con-nector van de Raspberry Pi heeft 26 pinnen. Deze zijn verdeeld in 17 echte input/output-pinnen, een I2C-interface, een SPI- interface, Serial Tx- en Rx-pinnen. Als je goed naar de Raspberry Pi kijkt, dan zie je dat er een recht-streekse verbinding is tussen de processor en de GPIO-pinnen. Alles wordt dus direct vanuit de processor aangestuurd.Kijken we naar het schema (figuur 1), dan zien we dat er per led (D1 t/m D5) ook een Foto 1: Het led-printje met de koperen kant boven

Eelco MeuterJava Software Architect bij Ordina.

Remko de Jong werkzaam bij Ordina als senior software developer.

Marco Hebing Java Software Architect is sinds anderhalf jaar werkzaam bij Ordina.

Raspberry.indd 28 5/1/13 2:52 PM

Page 29: Java Magazine #1 - 2013

JAVA MAGAZINE

MOBIELE ENTERPRISE-SERVER

Mobiele enterprise-serverJa-Pi is de eerste

P1 GPIO Led WiringPi

Pin 7 4 D1 7

Pin 11 17 D2 0

Pin 15 22 D3 3

Pin 21 9 D4 13

Pin 26 7 D5 11

weerstand (R1 t/m R5) in serie is geschakeld om de stroom door elke led te beperken. Dit voorkomt beschadigingen aan de Raspberry Pi en de led’s. Een led werkt prima met 10mA en heeft daar-bij zelf maar 0,7V nodig. De GPIO-pinnen leve-ren 3,3V, waardoor er dus nog 2,6V overblijft die we met een weerstand veilig wegwerken. De weerstandswaarde kunnen we berekenen met de formule R(Ω) = U(V) / I(A). In dit geval 2,6V / 0,01A = 260Ω. Die weerstandswaarde is geen standaardwaarde, dus ronden we af naar boven en komen we uit op 270Ω. We hebben dit ledprintje op de eenvoudigste manier gemaakt. Daarbij komt de print, met de koperen kant boven, op de Raspberry Pi te liggen. De connector zit nu aan de onder-kant. De foto laat zien wat de bedoeling is. Alle andere componenten solderen we op de koperzijde, zodat ze niet de onderdelen van de Raspberry Pi kunnen raken.Vanaf P1-pin 7 (figuur 1) solderen we eerst de weerstand R1. Vanaf de andere kant van de weerstand gaan we door naar de lange aan-sluiting van led D1. De korte aansluiting van de led verbinden we door met pin 6 van P1, dit is de min, ofwel ground. Herhaal dit voor alle weerstanden en led’s in het schema. Om de GPIO-pinnen vanuit de processor aan te sturen, gebruiken we WiringPi, een library geschreven in C door Gordon Drogon. Let op! WiringPi gebruikt een eigen nummering voor de pinnen. Deze wijkt af van de GPIO- num-mers zoals benoemd in figuur 1. Om vanuit Java met WiringPi te kunnen pra-ten, gebruiken we Pi4J. Met Pi4J kunnen we de benodigde pinnen definiëren als output. Immers, wij schakelen de led’s aan of uit. Het definiëren van een pin kunnen we maar één keer doen. Het is dus belangrijk om na de initialisatie de referentie naar de pin vast te houden. Dit kan heel simpel door gebruik te maken van een singleton die de objectrefe-renties naar de pinnen beheert.Nu moeten we alleen nog een client bouwen om de singleton aan te roepen. Wij kozen voor een simpele JSP, maar je kunt natuurlijk ook je eigen front-end bouwen in bijvoorbeeld JavaFX. Vanuit het aansturen van led’s via een JSP is het natuurlijk nog maar een kleine stap naar een mobiele enterprise-applicatie.

Bouw je eigen mobiele Ja-Pi enterprise-serverIn dit volgende project richten we onze Rasp-berry Pi in als een enterprise-server en mon-teren we hem op een robot. De opbouw van het voertuig is niets meer dan een Raspberry

Pi op rupsbanden, uitgerust met een op een servo gemonteerde webcam, wifi, infrarood-sensoren en een paar rijregelaars en scha-kelaars. De beelden van de webcam worden realtime verwerkt via Motion, een Linux-tool voor live video capture. Links op figuur 2 zie je duidelijk de GPIO-con-nector. Rechts naast de GPIO bevinden zich de comparatoren voor de infraroodsensoren. Bovenaan het schema bevinden zich de con-nectoren voor de rijregelaars en servo.De besturing van de robot is beperkt tot het

Figuur 1: Schema van een Raspberry Pi Connector met ons ledproject

Tabel 1: Mapping van de de Raspberry Pi naar WiringPi

Raspberry.indd 29 5/1/13 2:52 PM

Page 30: Java Magazine #1 - 2013

30

JAVA MAGAZINE

versnellen en vertragen van de snelheid en het draaien van de robot en camera. Vooruit-rijden betekent dat we de snelheid van beide rupsbanden tegelijkertijd veranderen. We kunnen een bocht maken door de snelheid van de ene rupsband te verhogen ten opzichte van de andere band. Het aanpassen van de snelheid van de elektromotoren gebeurt via de rijregelaars.De opzet van de applicatie is vrij simpel. Er is een eenvoudige HTML5-pagina, waarmee we via AJAX-requests besturingscommando’s uitvoeren. Een aantal controllers vangt deze REST-calls op. We maken hiervoor gebruik van JAX-RS. In deze controllers injecteren we onze Robot-class. Deze class bevat de logica om de robot te besturen en bevat een refe-rentie van de UnitManager. De UnitManager-class stuurt commando’s uit naar de driver die de robot en camera besturen. Daarnaast leest de UnitManager de sensoren uit via WiringPi. Voor de applicatieserver kozen we in eerste instantie voor de IBM Websphere. Volgens de brochure is het nieuwe Liberty Profile geheel configureerbaar en gebruik je enkel de features die je nodig hebt. De eerste testen waren veelbelovend. Websphere Librerty Profile draaide al snel en gemakkelijk op onze Raspberry Pi. Na de toevoeging van CDI, een singleton bean, enkele asynchrone beans en een timerservice in onze applicatie, ging het echter mis. Dus exit IBM, welkom JBoss. Tijd voor de volgende uitdaging. Om de mo-toren en servo aan te sturen, schrijven we een commando vanuit onze applicatie naar Ser-voBlaster; een driver om servo’s en motoren

softwarematig aan te sturen. Dit moet multi-threaded gebeuren, want de twee rupsbanden moeten simultaan draaien. Je eigen threads beheren op een applicatieserver is niet aan te raden. Om dit te simuleren, maken we gebruik van een timerservice. Dit werkt als volgt. Stel, we willen de snelheid van de robot opvoeren. We creëren dan twee getimede events met een kleine time-out voor respectievelijk de linker- en rechterrupsband. Op de time-out van dit event voeren we het commando uit in een aparte thread. Het bovenstaand codevoorbeeld toont ook nog een RCUnit-class. Deze class is een data-container voor onder andere de nieuwe positie

Figuur 2: Schema voor de bouw van de robot

Figuur 3:

Applicatiearchitectuur

voor de aansturing van

de robot

HET PRAKTISCH NUT VAN DEZE MOBIELE APPLICATIE-SERVER IS ONS NOG NIET HELEMAAL DUIDELIJK, MAAR DAT MAG DE PRET NIET DRUKKEN.

HTML5

JSON

REST API

UnitManager

WiringPi

Command

Servoblaster

Raspberry.indd 30 5/1/13 2:54 PM

Page 31: Java Magazine #1 - 2013

JAVA MAGAZINE

@Singleton@Startuppublic class UnitManager

@Inject private UnitCommand command;

@Resource private TimerService timerService;

@Timeout public void executeCommand(Timer timer) command.execute((RCUnit) timer.getInfo()); /** * Creates a new command. * * @param timer interval at which command is executed * @param info Required data to be passed to command */public void createCommand( int timer, RCUnit info ) timerService.createSingleActionTimer( timer, new TimerConfig(info, false );

// rest of class

@Statelesspublic class UnitCommand @Asynchronouspublic void execute(RCUnit unit) writeCommandToServoBlaster(unit); // rest of class

en de grenswaarden van de betreffende servo of motor.Nadat het in elkaar zetten van de robot en het testen van de software, was het tijd om alle Linux-libraries, de applicatieserver en onze webapplicatie te installeren. Dit is erg makkelijk en na een paar minuten opstarttijd heb je beeld. Je kunt nu een mobiele applica-tieserver aansturen vanaf een website. Als bestuurder word je netjes gewaarschuwd voor een naderend object. Een eventuele botsing zorgt ervoor dat de motoren en servo geen stroom meer krijgen. Een simpele refresh van de webpagina herinitialiseert de robot en je kunt weer op weg. Mocht je nieuwsgierig zijn naar het eindresultaat, bekijk dan het YouTube-filmpje.

SHOPPINGLIST1 Raspberry Pi, Model B (versie 2)

Project 1< 5 led’s, maakt niet

uit welke kleur.< 5 weerstanden 270Ω,

0,25W< 26-polige (2x13)

female printheader< Stuk experimenteer-

print 4x5cm (waarbij drie gaatjes steeds verbonden zijn)

< Lichte soldeerbout, ongeveer 15W

< Soldeertin

Project 2< Onderstel Robot< 2 rijregelaars< 6V accupack +

acculader< Stuk experimenteer-

print< 4 micoswitches voor

de bumpers< 1 standaard servo< 2 IDC-connectoren

voor de rijregelaar< 2 infrarood afstand-

sensoren< 1 power switch< 1 diode 1N4004< 1 condensator

4700uF/10V< 1 flatcable 2x13 polig< 1 male printheader

2x13 polig voor flatcable

< 3 male printheader 1x3 polig voor servo en rijregelaars

< 1 IC LM2902N< 4x weerstand 220k< 2x weerstand 470k< 2x weerstand 1M< 1 WI-PI, wifi dongle< 1 webcam< 1 sinaasappelkistje< Verf en wat plamuur

REFERENTIESRaspberry Pi: http://raspberrypi.orgPin layout P1: http://elinux.org/Rpi_Low-level_peripheralsWiringPi: http://projects.drogon.net/raspberry-pi/wiringpiMotion: http://www.lavrsen.dk/foswiki/bin/view/Motion/WebHomeServoBlaster: https://github.com/richardghirst/PiBits/tree/master/ServoBlasterPi4J: http://pi4j.com/YouTube: http://www.youtube.com/user/RaspberryPiOrdina

Wij hopen dat deze projecten je inspireren en zijn erg benieuwd met welk (wild) idee jij binnenkort aan de slag gaat. Laat het weten aan de redactie van het Java Magazine. Wat het ook zal zijn, je zal er een hoop van leren en veel lol aan beleven. Veel plezier!

MOBIELE ENTERPRISE-SERVER

Ben jij ook eenChampions League speler?

Kijk voor onze vacatures op pagina 20/21 van dit magazine.

Advertentie

Raspberry.indd 31 5/1/13 2:54 PM

Page 32: Java Magazine #1 - 2013

32

JAVA MAGAZINE

Sikuli is een open source grafische scherm analyse tool en is ontwikkeld binnen het Massachusetts Institute of Technology (MIT). Sikuli werkt op basis van images en pixel vergelijking. Hierdoor is Sikuli implementatie onafhankelijk en kunnen er zowel web- als native clients mee getest worden. De Java API van Sikuli is gebruiksvriendelijk, doordat het een klein aantal simpele en intuïtieve methodes bevat. Door deze Java code te com-bineren met het page object pattern, kunnen er onderhoudbare en overzichtelijke GUI-testen worden gemaakt. Daarnaast maakt de integratie met JUnit het mogelijk om deze testen toe te voegen aan een (bestaande) au-tomatische build. Dit artikel geeft inzicht in het gebruik van Sikuli en de Java API en biedt handvatten om de testen onderhoudbaar op te zetten.

Positionering GUI testenOm GUI-testen beter te kunnen positioneren wordt er gekeken naar de test automation pyramid . De test automation pyramid (Fi-guur 1) geeft een indicatie van de verhouding testen per testsoort, dat wil zeggen unit-, integratie of systeem en acceptatie testen. De pyramid geeft geen indicatie wat er getest wordt. Unittesten kunnen bijvoorbeeld ook worden gebruikt om onderdelen van de UI te testen. In de pyramid staat de unit test laag voor een solide basis. Wellicht door externe wijzigin-gen valt er een test om, maar daarmee nog

niet de hele testset. Unittesten zijn fijnma-zig en testen slechts kleine delen van de ap-plicatie onafhankelijk van elkaar. Wijzigingen aan het systeem raken slechts een klein deel van de unittesten die eventueel onderhoud behoeven.De tweede laag is de service laag, ook wel de integratielaag genoemd. De service of inte-gratie testen in deze laag controleren of de verschillende componenten of services van een applicatie correct met elkaar integreren. De scope van een integratie test is dus aan-zienlijk groter, waardoor wijzigingen aan de applicatie ook sneller kunnen leiden tot het plegen van onderhoud aan de testen. De top bevat de UI testen. Hiervoor geldt het worst case scenario dataanpassingen aan het systeem ertoe kunnen leiden dat alle testen in deze laag onderhoud behoeven. De UI of ook wel systeem testen in deze laag testen volledige flows, waar-bij een enkele test een groot gedeelte van de applicatie code raakt.Bij het bepalen van het type test dat men schrijft, kan de stelregel gehanteerd worden dat een test op een zo laag mogelijk niveau wordt geplaatst. Logica in een methode dient getest te worden op unit test niveau. Testen op integratie of GUI testniveau raken deze logica uiter-

Grafische User Interface testen In ons dagelijkse werk wordt er veelvuldig gebruik gemaakt van automatische testen met als doel sneller opleveren met een vastgestelde kwaliteit. Grafische User Interface (GUI) testen worden om verschillende redenen minder vaak ingezet. Dit artikel behan-delt de positie van GUI testen in het landschap van mogelijke automatische testvor-men. Concreet worden ervaringen en best practices gedeeld over “Sikuli”, een popu-laire en flexibele open source GUI testtool.

Figuur 1 De Test Automation Pyramid

aanpassingen aan het systeem ertoe kunnen leiden dat alle testen in deze laag onderhoud behoeven. De UI of ook wel systeem testen in deze laag testen volledige flows, waar-bij een enkele test een groot gedeelte van de applicatie code raakt.Bij het bepalen van het type test dat men schrijft, kan de stelregel gehanteerd worden dat een test op een zo laag mogelijk niveau wordt geplaatst. Logica in een methode dient getest te worden op unit test

met Java en Sikuli

Hubert ten Hove Werkzaam bij Info Support als Ontwikkelaar / Ontwerper

Sikuli.indd 32 5/1/13 2:56 PM

Page 33: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

ScreenRegion screen = newDesktop ScreenRegion();ImageTarget button = new ImageTarget(new File(“c:\images\buttonImage.png”));ScreenRegion buttonRegion = screen.find(target);DesktopMouse mouse = new DesktopMouse();mouse.click(buttonRegion.getCenter());

Grafische User Interface testen

Figuur 3 Sikuli Code voorbeeld

ImageTarget target = new ImageTarget(new File(“c:\images\buttonImage.png”));target.setMinScore(0.95d);

Figuur 4 Pattern Code voorbeeld

aard wel indirect, maar deze typen testen mogen niet als doel het testen van die methode hebben. Lager in de piramide geplaatste testen zijn niet alleen goedkoper om te maken, maar geven ook sneller nuttige feedback. Des te hoger een test in de piramide, des te meer setup hij behoeft en hoe complexer de test vaak is. Daarnaast kunnen hoger geplaatstse testen pas geschreven worden als er grote delen van de applicatie klaar zijn. Een GUI test wordt niet voor niets vaak een systeem test genoemd. Dit geeft aan hoeveel functionaliteit een applicatie al moet bezitten voor de GUI test gemaakt kan worden. Voor het maken van deze GUI-testen wordt er gebruik gemaakt van Sikuli.

SikuliSikuli werkt op basis van pixel vergelij-king. Het zoekt naar images op het scherm en vergelijkt deze met opge-slagen images. Het vergelijken van de images gaat op basis van een thres-hold, welke default op 80% is inge-steld. Dit betekent dat een image, op pixel niveau, voor 80% overeen moet komen. Naast de threshold kunnen er verschillende instellingen gedaan wor-den zoals zoeken op geschaalde of ge-draaide images. Daarnaast kan Sikuli ook tekst op het scherm herkennen. Door puur grafisch te werken op basis van pixel vergelijking, is Sikuli totaal onafhankelijk van een framework of implementatie. Andere GUI testtools, zoals Rational Functional Tester , SWTBot of Selenium , haken direct in op specifieke GUI frameworks, en zijn daardoor complexer en sterker gekop-peld aan de gebruikte technologie.De functionaliteit van Sikuli wordt ontsloten door een Java API. De twee belangrijkste klassen in deze API zijn DesktopScreenRegion, DesktopMouse en ImageTarget. De DesktopScreen-Region wordt gebruikt om het scherm te benaderen, en biedt methodes om images op het scherm te vinden en om delen van het scherm te benade-ren. De DesktopMouse klasse wordt gebruikt om muisklikken te kunnen simuleren op het scherm. Sikuli werkt op basis van images, de ImageTarget klasse is de Sikuli implementatie van een image. De basis van Sikuli werkt erg simpel,

zie het code voorbeeld in Figuur 3. Maak een instantie van DesktopS-creenRegion en een ImageTarget aan. Door de find methode wordt het image op het scherm gevonden. De methode retourneert een ScreenRegion waar het gevonden image zich bevindt, en null als het niet gevonden wordt. Via de DekstopMouse klasse kan er geklikt worden op coördinaten in het scherm. Deze krijgt als waarde mee het cen-trum van de gevonden ScreenRegion.De ImageTarget klasse kan aange-maakt worden door middel van een File maar ook door een URL. Verder bied de klasse de mogelijkheid om de evaluatie criteria in te stellen. Denk daarbij aan criteria als het percentage wat overeen moet komen (threshold). Het code voorbeeld in Figuur 4 toont het gebruik van ImageTarget waarbij de setMinScore methode het thres-hold instelt op 95%.

Het Page Object PatternGUI-testen vergen vaak veel setup, dit maakt de setup code lang, onleesbaar en niet onderhoudbaar. Het pageob-ject pattern biedt een oplossing voor deze problematiek. De pageobjecten modeleren een applicatie aan de hand van zijn schermen en dialogen. Page-objecten zijn in code geschreven repre-sentaties van grafische schermen of delen van deze schermen. Een grafisch scherm bevat een aantal knoppen, of andere interactie punten of toont een presentatie van data. Het pageobject modelleert elk scherm aan de hand van zijn interacties. Elke interactie van een scherm wordt een methode van het pageobject. Als een interactie op een scherm resulteert in het openen van een scherm of dialoog, zal pageobject dit ook implementeren. De methode van het pageobject zal

een pageobject van het nieuwe scherm terug geven. De unittesten benaderen de applicatie door middel van zijn pageobjecten.Het onderstaande sequence diagram (Figuur 5) toont hoe vanuit een unit-test de applicatie gestart en ingesteld kan worden. De starter klasse zorgt voor het opstarten van de applicatie. Na het starten van de applicatie geeft de klasse een pageobject terug van het login dialoog. Het pageobject geeft toegang tot het logindialoog. Het dialoog pageobject biedt de moge-lijkheid om in te loggen. Deze geeft dan een pageobject van het applicatie hoofdscherm terug. De unittest opent vervolgens een dialoog om instellin-gen aan de applicatie te doen.De implementatie van een pageobject wordt toegelicht aan de hand van een voorbeeld. Er wordt een pageobject gecreëerd voor een opslaan dialoog (Figuur 6). Het dialoog kent een viertal acties:< Opslaan< Annuleren< Browse< Bestandsnaam opgevenHet pageobject voor dit dialoog zal deze acties als methodes implemen-teren. De code voor het basis pageob-ject ziet er uit als het codevoorbeeld in Figuur 7. De constructor zoekt het dialoog op basis van een image. Het gevonden image wordt opgeslagen als de Region waarbinnen de verdere zoekopdrachten gedaan worden. Dit versnelt het zoekproces aanzienlijk omdat je nu alleen binnen een be-paalde region verder hoeft te zoeken en niet het hele scherm.De klasse wordt daarna uitgebreid met de acties van het dialoog. Opslaan en annuleren zijn eenvoudig te imple-menteren, door een clickmethode

GUI TESTEN MET JAVA EN SIKULI

Sikuli.indd 33 5/1/13 2:56 PM

Page 34: Java Magazine #1 - 2013

34

JAVA MAGAZINE

Figuur 5 Sequence Diagram

Figuur 6 Opslaan dialoog

public class SaveDialoog private ScreenRegion dialoog;

public SaveDialoog() ScreenRegion screen = new DesktopScreenRegion(); ImageTarget dialoogImage = new ImageTarget (“C:\images\VolledigeDialoog.png”); dialoog = screen.fi nd(dialoogImage);

Figuur 7 Code Voorbeeld page object

aan te roepen via een image region van de button. Het gebruik van de region helpt hierbij, hierdoor is er de zekerheid dat er nergens anders op het scherm een zelfde button staat. De browse button opent een nieuw dialoog. Het aanroepen van deze me-thode returned dan ook een pageob-ject van dit nieuwe dialoog. Naast het opslaan en annuleren kan er een browse dialoog geopend worden. De browse methode geeft dan een pageobject terug voor het browse dialoog dat geopend zal worden op het scherm. De laatste actie is het opgeven van een bestandsnaam. Voer een klik uit in het centrum van het image uit Figuur 9. Hierdoor zal de cursor in het bestandsnaam veld komen te staan. Daarna kan er via de DesktopKeyboard klasse tekst in geplaatst worden.

JUnitDoor de pageobjecten te gebruiken wordt een setup van een unittest overzichtelijk en leesbaar. De setup vergt vaak niet meer dan een aantal regels code. Het volgende code voorbeeld (Figuur 9) laat zien hoe de setup van een unit-test in de applicatie er uit ziet. Dit is de implementatie van het sequence

diagram uit Figuur 5. Het opstarten van de client en het inloggen is iets wat bij voorkeur gedaan wordt in de setup van de klasse en niet voor elke unittest opnieuw. Dit kan door een setup methode met de @Before-Class tag op te nemen. Het afsluiten gebeurt dan in een teardown methode met een @AfterClass tag. De client moet voor elke unittest terug gebracht worden naar een bepaalde uitgangspositie. Een falende unit-test heeft hierdoor geen invloed op de opvolgende testen. Dit kan zelfs betekenen dat het verstandig is om de gehele client af te sluiten en opnieuw te starten. Na de setup van de test moeten de controles uitgevoerd worden. Si-kuli assert de client aan de hand van images. Deze images representeren de client met de juiste schermen en met de juiste gegevens op het scherm. Hiervoor wordt gebruik gemaakt van de find methode in Sikuli in combina-tie met de default threshold van 80% of door deze in te stellen (Figuur 10).

UitdagingenBij het maken van de testen zijn er de volgende uitdagingen:< GUI-testen zijn breekbaar en vergen

in vergelijking tot integratie of unit

testen veel onderhoud.< Het zoeken van images op het

scherm is langzaam;< GUI-testen moeten een zinnige

foutmelding geven;< Instellen van de threshold voor

een image;

Onderhoudbaarheid GUI-testenHet pageobject pattern scheidt de setup test code van de daadwerkelijke testen, wat hergebruik over verschil-lende testen bevordert. Door gebruik te maken van het pattern worden de testen leesbaarder en beter onder-houdbaar. Door de applicatie op te de-len in schermen hoeft men alleen het pageobject van het gewijzigde scherm aan te passen. Dit zal op de GUI testen zelf weinig tot geen effect hebben.

Performance bij zoekenPageobjecten maken gebruik van de Screen klasse om toegang te krijgen tot het scherm. Om de zoekopdrach-ten te versnellen wordt het scherm opgedeeld in regions. Dit opdelen kan door het opgeven van coördinaten, maar ook op basis van de zoek resul-taten (Figuur 7). Niet alleen versnelt het opdelen de testen maar voorkomt het ook de kans op fouten. Vooral bij het zoeken naar images die vaker kun-

Sikuli.indd 34 5/1/13 2:56 PM

Page 35: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

GUI TESTEN MET JAVA EN SIKULI

Figuur 9 Sikuli zoek image

LoginDialoog loginDialoog = new MidClientOpstarter().startMidClient();Client client = loginDialoog.login(“gb”, “gb”);InstellenInhoudDialoog dialoog = client.openInstellenInhoudDialoog();dialoog.setTijd(Ma, 12:00, Di, 4:00);dialoog. …dialoog.ok();

Figuur 10 Setup Code van een Unittest

DesktopScreenRegion screen = new DesktopScreenRegion();ImageTarget imageTarget = new ImageTarget(new File(“c:\images\image.png”));imageTarget.setMinScore(0.99d);ScreenRegion exists = screen.fi nd(imagePattern); if (exists == null) fail(“Het image wordt niet of niet juist weer gegeven.”);

Figuur 11 Voorbeeld “assertion” using Sikuli

public void cancel() ImageTarget button = new ImageTarget(new File(“c:\images\cancelButton.png”)); ScreenRegion buttonRegion = dialoog.fi nd(button); if(buttonRegion != null) mouse.click(buttonRegion.getCenter()); else fail(“De cancel button kan niet gevonden worden.” + SikuliTool.saveScherm(dialoog, “C:\images\cancelButton.png”));

Figuur 12 Fail in pageobjecten

nen voorkomen op het scherm, denk hierbij aan een ‘Ok’ knop.

FoutmeldingenZoals altijd met het schrijven van code is het ook voor GUI testen erg belangrijk zinnige foutmeldingen te genereren. Sikuli geeft null terug als een image niet gevonden wordt op het scherm. Er moet een keuze gemaakt worden om dit af te handelen in de unittest d.m.v. een exception of in het pageobject. De keuze valt op het direct afhandelen in het pageobject (Figuur 11). Hier kan namelijk een duidelijke foutmelding gegenereerd worden op basis van de bekende gegevens.Het pageobject handelt een niet gevonden image af door een fail aan te roepen. De fail methode faalt de unittest die gebruik maakt van het pageobject. Best practice is het maken van een screenshot om de foutmel-ding te ondersteunen. Er is een eigen SikuliTool klasse gemaakt welke op basis van een meegegeven Region een screenshot maakt en saved. De save methode geeft een melding terug met daarin de locatie van het screenshot en een verwijzing naar het gezochte image op het scherm. Deze visuele feedback op de falende unittesten is zeer waardevol tijdens het debuggen en om te bepalen waarom een nightly build gefaald is.

Instellen thresholdOm testen betrouwbaar te maken is het instellen van een goede thres-hold belangrijk. Als de threshold te licht ingesteld wordt zal Sikuli te veel herkennen. Met een te zwaar ingestelde threshold kunnen testen falen. Een threshold van 100% is niet aan te raden. Er treden in een client altijd kleine verschillen op door anti aliasing of een schaduw die net iets anders berekend is. Voor native clients kunnen verschillende Windows themes ook problemen geven. Als best practice wordt een threshold van 98% aangeraden als iets volledig goed op het scherm dient te staan. Sikuli herkent de meeste GUI items met de default instellingen.

ConclusieOndanks dat de Sikuli tool zich nog in versie 1.0 RC3 bevindt wordt het

al twee jaar ingezet bij een klant van ons. Het heeft ons al meerdere malen nuttige feedback gegeven. De falende GUI testen zijn een indicatie van mis-sende unittesten. Deze moeten dan ook uitgebreid worden. De roadmap voor de 1.0 release is sinds november 2012 beschikbaar evenals een stand-alone Java API.Het gebruik van het pageobject pat-tern komt de onderhoudbaarheid van de testen ten goede en wordt als zeer prettig ervaren. Een aanpassing aan een venster in de client betekent niet meer dan een aanpassing aan een pa-geobject, zonder de unittesten aan te hoeven passen. Mede door een goede foutmelding met het bijgeleverde screenshot waren de falende testen snel te debuggen. Het kwam niet vaak voor dat een test opnieuw gestart

moest worden en een ontwikkelaar de acties op het scherm moest volgen om de fout te ontdekken. De screenshots zijn een uitkomst.Sikuli en pageobject pattern ma-ken het makkelijk om GUI testen te schrijven. Sikuli heeft een korte leercurve. Een ontwikkelteam heeft het binnen een paar dagen goed onder de knie. Hierdoor kan er met weinig tijd en moeite een onderhoudbare en begrijpbare set GUI testen gecreeerd worden. Dat is de grote kracht bij het gebruik van Sikuli met het pageobject pattern.

Sikuli.indd 35 5/1/13 2:57 PM

Page 36: Java Magazine #1 - 2013

36

JAVA MAGAZINE

Java MagazineWe zijn terug! Na een jaar uit de lucht geweest te zijn, presenteren we als bestuur met trots het vernieuwde Java Magazine. Begin 2012 werden we overvallen door het nieuws dat de uitgever ten onder was gegaan aan een faillissement. Na een uitgebreide zoektocht naar een nieuwe me-diapartner voor de NLJUG, zijn we verheugd om te melden dat we het blad nu volledig in eigen beheer maken en uitgeven. Niet in de laatste plaats dankzij de hulp van een aantal enthousiaste NLJUG leden die de redactiecommissie van het blad vormen. Wil je zelf graag bijdragen door iets te schrijven voor het magazine? Aarzel dan niet en neem contact met ons op!

Organisatieveranderingen NLJUGOndanks dat we niet zichtbaar waren in de vorm van een magazine, zijn we in 2012 zeker niet onzichtbaar geweest. Naast een conferentie en andere events, vond een belangrijk deel van wat er het afgelopen jaar is gebeurd echter plaats achter de scher-men. Een Java User Group is een complex ding. Een JUG van de grond krijgen is mak-kelijk. Alles wat je nodig hebt zijn een paar enthousiaste mensen en een plek om bij elkaar te komen. De eerste paar maanden of jaren kost het vrijwel geen moeite om dat kunstje te blijven herhalen. Echter, zodra

Van het bestuurEen update vanuit het NLJUG bestuur, met dit keer nieuws over Java Magazine, aandacht voor organisatieveranderingen binnen de NLJUG, een terugblik op J-Fall 2012 en een vooruitblik op de rest van het jaar.

je ledenaantallen fors gaan groeien en je ‘zaken’ gaat doen met businesspartners, evenementenbureau’s en mediapartners verander je langzaam van een club enthousi-astelingen bij een thema tot een bedrijf. Om die fase te overleven moet je je ook gaan gedragen als bedrijf. En dat betekent dat de spaarzame avonduren en regenachtige zon-dagmiddagen ineens gevuld gaan worden met saaie bezigheden als ledenadministra-tie, boekhouding, projectleiding en wat al niet meer. Aangezien de NLJUG voor geen van de bestuursleden een day-job is, hebben we ons de afgelopen jaren met vallen en opstaan door die dynamiek heen gewerkt. Sinds 2003 (ja, ja, 2013 is daarmee dus een bijzonder jaar!) zijn we de NLJUG in haar huidige vorm aan het rollen. Om ook de komende 10 jaar dezelfde en verbeterde continuïteit te bieden, hebben we als be-stuur het besluit genomen, om de volledige operationele activiteiten van de NLJUG onder te brengen in een BV die daarbij zowel het secretariaat (leden- en financiële admi-nistratie), het magazine, de website en de evenementen gaat uitvoeren. Deze BV ‘zit er ondernemend in’ en heeft veel ervaring met het runnen van vergelijkbare communities in aanpalende vakgebieden. Maar wees gerust, de identiteit van de NLJUG zal ten alle tijden worden bewaakt door de stichting en het bestuur. We gaan de boel niet commercieel uitventen.

Bert ErtmanBestuurslid NLJUG

Java Magazine

is TERUG

Bestuurscolumn.indd 36 5/1/13 2:59 PM

Page 37: Java Magazine #1 - 2013

JAVA MAGAZINE | 01 2013

VAN HET BESTUUR

Van het bestuur

Mede als gevolg van de organisatiever-anderingen is er na 10 jaar NLJUG ook een einde gekomen aan de betrokkenheid van een aantal oudgediende bestuursleden. Per 1 april 2013 hebben we als NLJUG bestuur afscheid genomen van Klaasjan Tukker en Hans Bossenbroek. Vanaf deze plaats wil-len we hen ontzettend bedanken voor de grenzeloze inzet die zij geheel belangeloos hebben getoond, om de NLJUG door weer en wind gestalte te geven en uit te bou-wen. Door inzet van hen beiden is de NLJUG opgericht en uitgebouwd tot het succesver-haal wat we vandaag de dag zijn. Als dank voor hun inzet zijn ze erelid van de NLJUG geworden.

J-Fall 2012Het is al bijna weer een half jaar geleden, maar er valt nog steeds na te genieten van J-Fall 2012. Op de website vind je een te-rugblik in de vorm van een video-impressie en verwijzingen naar blogs, de fotogalerij en de resultaten van de evaluaties. Ook zijn de presentaties van bijna alle sessies te downloaden. Ongeveer de helft van de presentaties van J-Fall 2012 is op video op-genomen en terug te kijken op Parleys.com. Kijk hiervoor bij ‘spaces’ in het NLJUG chan-nel. De presentaties zijn tevens te bekijken via de speciale NLJUG iPad App die je kunt vinden in de Appstore. Clients voor andere platforms zijn in de maak.

Vooruitblik op 2013In 2013 gaan we vooralsnog eerst maar eens verder op de bekende weg. University ses-sies voor kennisverbreding, een vernieuwde website, uiteraard J-Fall 2013 en natuurlijk weer een Magazine. Met de vernieuwde slagkracht die we als organisatie heb-ben gekregen kunnen we vervolgens onze dienstverlening naar zowel de leden als de businesspartners verder uitbouwen. Op 15 april j.l. hebben we daarvoor met onze bu-sinesspartners om de tafel gezeten. Leden met ideeën worden van harte uitgenodigd te reageren via twitter (@NLJUG), de mail ([email protected]) of door een van de be-stuursleden te benaderen.Al met al kijken we terug op een heftige periode. Interessante veranderingen in de organisatie brengen een vernieuwd com-mitment en continuïteit. Afscheid nemen van mensen die het fundament onder de NLJUG zijn geweest geeft een dubbel gevoel, maar loslaten en anderen het verder laten brengen is tevens een kenmerk van groot vertrouwen in de toekomst.

Future.get();

Ben jij ook eenChampions League speler?

Kijk voor onze vacatures op pagina 20/21 van dit magazine.

Advertentie

Bestuurscolumn.indd 37 5/1/13 3:22 PM

Page 38: Java Magazine #1 - 2013

38

JAVA MAGAZINE

COLUMN

Meer met Maven Least Fat Executable JarIn elke editie van het Java Magazine zal Robert Scholte een probleem voorleggen en deze oplossen met behulp van Maven, om meer inzicht te geven in Maven zelf en de vele beschikbare plugins.

Robert ScholteIT Consultant voor CGI, teamlid van Apache Maven.

Stel dat ik een class met deze ogenschijnlijk simpele methode wil uitvoeren als executable jar, dan heb ik een interessante uitdaging: hoe krijg ik de dependencies naar SLF4J op het classpath?Voor het uitvoeren van dit soort standalone applicaties zijn er een klein aantal opties. De meest klassieke oplossing is het verzamelen van alle jars (wat kan via dependency:copy-dependencies) en alles uitschrijven op de com-mandline:Door een manifest-file op te nemen in de jar

kan ik dit al een stuk vereenvoudigen, want daarin kan ik zowel het classpath als de Main-class opgeven. Vandaar dat bijna alle ‘packaging’-plugins voorzien zijn van een optie <archive><manifest/></archive>, waarin je dit soort details in kwijt kunt. In dit geval gaat het om de opties <addClasspath/> en <mainClass/>. Op dit moment bestaat deze deliverable uit meerdere bestanden, maar mijn wens is om dit terug te brengen tot één bestand, oftewel een ‘fat jar’. Het opnemen van jars in een jar is weliswaar in theorie mogelijk, maar daarmee komt de dependency-jar zelf op het classpath en niet de inhoud van deze jar. De enige optie die je hebt, is door ervoor te zorgen dat alle bestanden van de verschillende jars gebundeld worden in één jar.

public static void main( String[] args ) org.slf4j.LoggerFactory.getLogger( Eric.class ) .warn( “I’m not fat! I’m getting in shape!” );

De eerste plugin waarmee dit mogelijk werd was de Maven Assembly Plugin, maar tegen-woordig is er een plugin die hier veel beter op aansluit, namelijk de Maven Shade Plugin. Zon-der enige aanpassing aan de configuratie maakt deze plugin van je project al direct een fat-jar . Nadat ik met fat-jar heb gegenereerd heb ik weliswaar alle classes samengepakt in één jar, maar de kans is zeer groot dat slechts een klein deel van alle beschikbare bestanden gebruikt wordt. Het zou heel mooi zijn, als ik de jar kon ontdoen van onnodige ballast. Met de optie <minimizeJar> is het mogelijk alleen de gebruikte classes op te nemen in de jar . Met de volgende configuratie transformeer ik mijn project tot de meest compacte executable jar:

Voor de minimizeJar is een kleine kanttekening: dit werkt alleen zolang er naar de classes gere-fereerd wordt. Het zal niet werken als er gebruik gemaakt wordt van reflection in de code, zoals bijvoorbeeld Class.forName(“crazy.old.Driver”).Bekijk http://maven.apache.org/plugins/maven-shade-plugin/ voor verdere details en andere mogelijkheden met de Maven Shade Plugin.

.\target>java -cp awesom-0.4000-SNAP-SHOT.jar; dependency\slf4j-api-1.5.6.jar;dependency\slf4j-simple-1.5.6.jar cgi.maven.nljug.Eric

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.0</version> <executions> <execution> <goals> <goal>shade</goal> </goals> <confi guration> <transformers> <transformer implementation=”org.apache.maven.plugins.shade.resource.ManifestResourceTransformer”> <mainClass>cgi.maven.nljug.Eric</mainClass> </transformer> </transformers> <minimizeJar>true</minimizeJar> </confi guration> </execution> </executions></plugin>

Column Maven.indd 38 5/1/13 3:01 PM

Page 39: Java Magazine #1 - 2013

Nederlands of Java?

Jij spreekt het allebei.

Ideeën van onze klanten

vertaal jij eenvoudig in

nieuwe technologie.

Jij weet wat Java kan.

Maar weet Java al wat

jij kan?

Geef richting aan je ontwikkeling!71.000 professionals gingen je voor. Nu jij nog!

Kijk op www.werkenbijcgi.nl voor de JAVA-vacatures. Liever eerst informeren naar de mogelijkheden? Bel met Jaap van den Broek (HR - Team) via 088 - 5640000.

Maar weet Java al wat

jij kan?

Snel profiteren van nieuwe technische mogelijkheden. Dat willen onze klanten. Of het nu gaat om een innovatieve applicatie of verbetering van een bestaand systeem. Met Java is alles mogelijk. Omdat de techniek overal toegepast kan worden, zijn de mogelijkheden oneindig.

Jij kent Java en kan onze klanten helpen om hun doel te bereiken. Heeft de klant een complexe keten van informatiesystemen? Jij bedenkt en bouwt een website waarin alles overzichtelijk samenkomt. En ook voor nieuwe technieken met Google Android kunnen we je natuurlijk inschakelen. En je draait je hand niet om voor nieuwe uitdagingen, zoals het bedenken van veilige software voor betaling aan de ‘pomp’ bij elektrisch rijden. Jouw expertise is de toekomst.

We vragen veel van je. Kennis van het vak, enthousiasme en doorzettingsvermogen. CGI heeft namelijk alleen de beste mensen in dienst. Onze klanten weten dat ook. Daarom kunnen wij jou de meest interessante opdrachten aanbieden. Want met jouw ervaring kun je de meest innovatieve, technische en complexe opdrachten aan.

Voor jouw inzet krijg je wat terug. We bieden je bijvoorbeeld alle ruimte om je te ontwikkelen. Start je als software engineer, dan kun je doorgroeien naar IT consultant of architect. Heb je managementambities, dan kun je ook team lead worden. We stimuleren je in jouw ontwikkeling, maar rekenen erop dat je zelf het voortouw neemt. Met ons certificeringstraject maak je jouw kennis aantoonbaar. Goed voor de klant, goed voor jou.

Experience the commitment

Untitled-2 1 24-4-2013 9:26:58

Page 40: Java Magazine #1 - 2013

INNOVEER JIJMETONSMEE?

Bert van den Belt en Huub Jansen, directeuren Java Ordina

De terugkeer van JAVA Magazine is een heuse verrijking voor het vak, vinden we bij Ordina. Meer kennis helpt je immers om jezelf te ontwikkelen. Daarom organiseren we regelmatig workshops, trainingen en presentaties. Zo ook weer binnenkort.

13 juni: Innoveer Jij Mee-sessie. Schrijf je nu in!

Kom op 13 juni naar onze Innoveer Jij Mee-sessie. Interactief, informatief en vooral: inspirerend. Een sessie over techniek, door en voor software ontwikkelaars en architecten, zoals jij. We beloven je: na afloop ben je helemaal up-tot-date met de actuele trends en ontwikkelingen rondom JAVA, het platform, de verschillende frameworks en tools. We zijn ook razend benieuwd naar jouw inbreng en jouw ideeën. Schrijf je in op werkenbijordina.nl. Zien we je dan?

werkenbijordina.nl

ICTMAARDANVOORMENSEN

javaman_magazine_advertentie.indd 1 26-04-13 13:24Untitled-1 1 29-4-2013 10:08:39