Stage Eindwerk Studiegebied Bachelor Afstudeerrichting Academiejaar Student Handelswetenschappen en Bedrijfskunde Toegepaste Informatica 2007-2008 Bram Gadeyne Thema Seam’s Like Future Een onderzoek naar de toepasbaarheid van een framework in Java Stageplaats Dolmen Huizingen & De Pinte Stage Eindwerk Studiegebied Bachelor Afstudeerrichting Academiejaar Student Handelswetenschappen en Bedrijfskunde Toegepaste Informatica 2007-2008 Bram Gadeyne Thema Seam’s Like Future Een onderzoek naar de toepasbaarheid van een framework in Java Stageplaats Dolmen Huizingen & De Pinte Woord Vooraf Toegepaste Informatica aan de Hogeschool West-Vlaanderen… de richting waar ik mijn kennis over informatica de laatste 3 jaar heb kunnen bijschaven. Aan het einde van de boeiende weg kwam de mogelijkheid om alle vergaarde kennis om te zetten in de praktijk. Ik ging hiervoor op zoek naar een informaticabedrijf die naast een grote omvang en een goede naam ook al een langere tijd actief is op de markt. Ook wou ik dat mijn stage me kijk gaf op nieuwe technologieën en technieken in de programmeertaal Java. Ik wil allereerst Bart Van Loocke bedanken die me het bedrijf Dolmen aanraadde. Zij voldeden perfect aan mijn vereisten. Ze waren ook zeer enthousiast om mij een stage aan te bieden. Bij Dolmen liep ik een boeiende en leerrijke stage. Hiervoor wil ik dan ook mijn mentors Hans De Neve en Frederik Dierickx bedanken voor de hulp die ze me boden gedurende mijn stage. Ook mijn stagegever Silvia Di Bono wil ik bedanken voor de eerste ervaring met een sollicitatiegesprek en de mogelijkheid die ze me bood om stage te lopen bij Dolmen. Daarnaast wil ik ook mijn stagebegeleider Corneel Theben Tervile bedanken voor de begeleiding vanuit de hogeschool. Ook wil ik mijn medestagiaire Lisa Van Daele en alle medewerkers van Dolmen van harte bedanken voor de toffe werksfeer die de stage aangenamer maakte. Voornamelijk Tim Vandeplas die me technisch bijstond als ik een probleem had. Ook Pascal Vandaele waarmee ik het grootste deel van de tijd in De Pinte het bureau deelde en waarmee ik vele aangename gesprekken heb gehad. De grootste groep mensen die mij geholpen hebben, zijn mensen die ik nog nooit heb gezien en enkel ken via hun fictieve naam op het internet. Ik heb het hier over alle mensen die topics hebben behandeld op het JBoss forum en de ontwikkelaars van JBoss Seam of andere JBoss frameworks die via de JIRA sites oplossingen zochten en gaven voor problemen. Ook al was mijn stage geen groepsopdracht, de uitwerking zou zonder alle hier boven vernoemde mensen niet realiseerbaar geweest zijn. Eindwerk Bram Gadeyne Samenvatting Programmatie van grote enterprise webapplicaties is de dag van vandaag een hot topic in de programmeerwereld. Iedereen heeft er in de Java-wereld zo zijn eigen visie over. Men maakt gebruik van verschillende frameworks die bepaalde functies voor de gewenste applicaties aanbieden of voorzien in een volledige basisarchitectuur voor de applicatie. Door het gebruik van verschillende frameworks door elkaar verliest de applicatie op zich soms wat aan structuur. Sommige frameworks leggen zelfs bewust de Java-standaarden naast zich neer. Maar net naar die standaarden en compatibiliteit tussen verschillende frameworks is er een grote vraag. Het Seam project van “JBoss, a devision of red hat” is een veelbelovend framework die een uitstekende oplossing kan bieden voor dit probleem. Eigenlijk is het doel van Seam om vaak gebruikte onderdelen zoals authenticatie, webpagina’s (view), business logica (EJB 3.0), testing, logging, mail afhandeling, creatie van PDF’s, databankondersteuning (met persistence), enz … te bundelen en direct, gemakkelijk en zonder al te veel configuratie beschikbaar te maken voor de programmeur. Web 2.0 compatibiliteit wordt voorzien door het gebruik van Richfaces die een uitstekende ondersteuning biedt voor AJAX. De integratie van deze frameworks en de webapplicatie architectuur werden uitgetest aan de hand van een competentie management systeem. Via verworven competenties kunnen werknemers bepaalde functies of opdrachten toegewezen krijgen waarvoor ze de benodigde competenties bezitten. Competenties kunnen verworven worden na het volgen van opleidingen van Dolmen of zelfstudie. “Seam’s like Future” is zeker geen misplaatste uitspraak bij dit framework. Seam maakt veel kans om in de toekomst heel vaak te worden gebruikt door de eenvoud en de grote productiviteit die het met zich meebrengt. Het succes van Seam kun je terugvinden bij de WebBeans. Dit is eigenlijk de standaard die uit Seam is voortgevloeid. Eindwerk Bram Gadeyne Abstract Programming giant enterprise wide web applications is nowadays a hot topic in the world of programming. Everyone in the Java-world has his own view on creating them. They use different frameworks which provide some functions for the desired web application. Or they provide a full basic architecture for it. Due to the use of different frameworks together, the application loses some of its structure. Some frameworks even consciously ignore the Javastandards. Nowadays there is a great demand for these standards and compatibility between different frameworks. The Seam project of “JBoss, a devision of red hat” is a promising framework which can provide a very good solution for these problems. In fact the goal of Seam is to bundle and provide rapid and easy access without to many configurations to the frameworks for the programmers. Examples of these frameworks are authentication, WebPages (view), business logic (EJB 3.0), testing, logging, mail handling, creating PDF files, database access (with persistence), … Web 2.0 compatibility is added by the use of Richfaces which provides a very good support for AJAX. The integration of these frameworks and the web application architecture were tested by a competence management program. By means of the gained competences employees can be assigned to some functions or tasks for which they have the competences needed. These competences can be gained by Dolmen trainings or by self-study. “Seam’s like Future” is not a wrongly placed expression for this framework. Seam has many opportunities to be used in the future by its simplicity and the great productivity it provides. The success of Seam can be found with the WebBeans. This is actually the standardisation of Seam. Eindwerk Bram Gadeyne Verklarende Woordenlijst Term AJAX Uitleg Is een afkorting voor assynchronious javascript and xml. De bedoeling van Ajax is om vragen en antwoorden asynchroon te kunnen verzenden en ontvangen van client naar server. Asynchroon wil zeggen dat de client niet zal wachten op het antwoord van de server maar dat hij de verwerking van het antwoord zal doen wanneer het antwoord terug bij de client toekomt. De gebruiker kan dus ondertussen verderwerken met de applicatie. Door het gebruik van XML, waarop HTML ook is gebaseerd, en javascript kunnen stukken HTML vervangen worden door andere zonder dat de pagina door de webbrowser volledig opnieuw moet worden geladen. Hierdoor krijg je het effect alsof je op een gewone desktop applicatie aan het werken bent. Bindings In JSF gebruikt men vaak bindings om een bepaalde waarde te koppelen aan een object. Die koppeling op zich klinkt simpel maar dankzij JSF moet er geen rekening meer gehouden worden met het gebruik van POST of GET variabelen of andere manieren om data uit bijvoorbeeld een tekst veld in een bepaalde value van een object op te slaan. CORBA Common Object Request Broker Architecture, is een standaard voor de communicatie tussen objecten, geschreven in verschillende programmeertalen en draaiend op verschillende machines. ORB's (Object Request Brokers) worden geleverd door verschillende bedrijven en zijn gebaseerd op IIOP (Internet Inter Orb Protocol), waardoor in principe clients en servers, onafhankelijk van de gebruikte ORB, met elkaar kunnen praten. EL (Expression Dit is een onderdeel van JSF die het mogelijk maakt om bindings te maken Language) tussen een JSF pagina en backing beans. Met EL kun je ook berekeningen uitvoeren of bepaalde voorwaarden controleren in een JSF pagina. Framework Een Framework bestaat meestal uit een aantal objecten of packages die voorzien in bepaalde functionaliteiten voor een applicatie. Het is eigenlijk een verzameling van code die ter beschikking wordt gesteld van andere programmeurs zodat ze voor dezelfde problemen de al gevonden oplossingen kunnen gebruiken. Sommige frameworks voorzien ook in een goede integratie van een bepaalde applicatie architectuur. JIRA-sites Dit is een groep van Bug Tracking sites. Ze worden gebruikt om van een bepaald project bugs te kunnen beheren. Je kunt er dan ook zien wie met welke bugs bezig is en of er eventueel al oplossingen voor gevonden zijn. Eindwerk Bram Gadeyne Loosely Coupled Objecten zijn lously coupled als ze elkaar via een interface kunnen benaderen en geen effectieve referentie naar elkaar moeten bijhouden. Op die manier kunnen gedragingen of implementaties van objecten gemakkelijk veranderd worden at runtime. POJO Is een afkorting voor een Plain Old Java Object. Dit is eigenlijk een andere naam voor een gewone basis Java klasse. Proven Technologie Technologie waarvan de bedrijfswereld vindt dat ze zichzelf al meerdere malen heeft bewezen. Meestal gaat dit gepaard met grote projecten die een bepaald framework of techniek als referentie kan opgeven. Web 2.0 Web 2.0 is een begrip die binnen de webwereld de laatste tijd veel gebruikt wordt. Helaas bestaat er geen echte definitie van Web 2.0 omdat Web 1.0 nooit is beschreven en omdat Web 2.0 een toekomstvisie is zoals men graag de websites naar een nieuw niveau zou willen laten zien veranderen. Dankzij frameworks als Richfaces die gebruik maken van Ajax om hun componenten af te laten beelden en laten samenwerken met elkaar krijg je al een mooi voorbeeld van hoe Web 2.0 eruit zou kunnen zien. PO Een persoonlijke overleg tussen een chef en een medewerker. Eindwerk Bram Gadeyne Inhoudsopgave Woord Vooraf .......................................................................................................................... 4 Samenvatting ........................................................................................................................... 5 Abstract .................................................................................................................................... 6 Verklarende Woordenlijst ...................................................................................................... 7 Inhoudsopgave ......................................................................................................................... 9 1 Voorstelling van het bedrijf ........................................................................................... 12 2 Stageopdracht ................................................................................................................. 14 3 Analyse ............................................................................................................................ 15 3.1 Doelstelling .............................................................................................................. 15 3.2 Bestaande situatie ..................................................................................................... 15 3.3 Functionele eisen ...................................................................................................... 16 3.4 Niet-functionele eisen .............................................................................................. 17 3.5 Randvoorwaarden ..................................................................................................... 17 3.6 Use case diagrams .................................................................................................... 17 3.6.1 Beheer Competentiefiche.................................................................................. 18 3.6.2 Beheer Opleiding .............................................................................................. 19 3.6.3 Beheer Actieplan .............................................................................................. 20 3.6.4 Beheer Functiebeschrijving .............................................................................. 21 3.7 Rapporten ................................................................................................................. 22 3.8 Beschrijving gebruikers ............................................................................................ 22 3.8.1 Personeelsverantwoordelijke ............................................................................ 23 3.8.2 Personeelssecretariaat ....................................................................................... 23 3.8.3 Chef................................................................................................................... 23 3.8.4 Medewerker ...................................................................................................... 23 3.9 Rechten gebruikers ................................................................................................... 23 4 Ontwerp........................................................................................................................... 24 4.1 Logisch ..................................................................................................................... 24 4.1.1 Data-analyse / Datamodel ................................................................................. 25 4.1.2 Objectgeoriënteerd model ................................................................................. 26 4.2 Architectuur .............................................................................................................. 30 4.2.1 Application Architecture .................................................................................. 30 4.2.2 Platformonafhankelijkheid ............................................................................... 31 4.3 Technisch ................................................................................................................. 32 4.3.1 Java 5 ................................................................................................................ 33 4.3.2 EJB 3.0 .............................................................................................................. 34 4.3.3 JSF .................................................................................................................... 37 4.3.4 Seam ................................................................................................................. 41 4.3.5 Rich Web Applications (Web 2.0).................................................................... 45 4.3.6 Seam Logging ................................................................................................... 54 Eindwerk Bram Gadeyne 5 Seam Mail ......................................................................................................... 55 4.3.7 4.3.8 Seam Timer ....................................................................................................... 56 4.3.9 Seam Timer met Seam Mail ............................................................................. 57 4.3.10 Seam authenticatie ............................................................................................ 57 4.3.11 Seam Fileupload/filedownload ......................................................................... 58 4.3.12 Seam Taalondersteuning ................................................................................... 61 4.3.13 Persistence – Hibernate..................................................................................... 61 4.3.14 Rapportering ..................................................................................................... 64 4.3.15 Testing .............................................................................................................. 66 4.3.16 Exception handling ........................................................................................... 69 4.3.17 Servers .............................................................................................................. 69 Programmatie ................................................................................................................. 73 5.1 Gebruikte hardware .................................................................................................. 73 5.2 Gebruikte software ................................................................................................... 73 5.2.1 Besturingssystemen .......................................................................................... 73 5.2.2 Servers .............................................................................................................. 73 5.2.3 IDE .................................................................................................................... 74 5.2.4 Programmeertalen ............................................................................................. 75 5.2.5 Tekstverwerkers ................................................................................................ 75 5.2.6 Beeldverwerker ................................................................................................. 76 5.2.7 Varia ................................................................................................................. 76 5.3 Een nieuw project starten ......................................................................................... 77 5.3.1 Installatie van Eclipse ....................................................................................... 78 5.3.2 Installatie van de JBoss Tools........................................................................... 79 5.3.3 Installatie van de Seam Runtime ...................................................................... 82 5.3.4 Creatie van een nieuw Seam project. ................................................................ 83 5.3.5 Het project starten ............................................................................................. 94 5.3.6 Werken met de JBoss Tools ............................................................................. 95 5.3.7 Richfaces drag and drop demo ......................................................................... 95 5.4 Algoritmes ................................................................................................................ 98 6 Bespreking van het programma .................................................................................. 100 6.1 Gebruikershandleiding ........................................................................................... 100 6.1.1 Gebruikerstypes .............................................................................................. 100 6.1.2 Algemeen ........................................................................................................ 100 6.1.3 Het admin paneel ............................................................................................ 106 6.1.4 Het Gebruiker Menu ....................................................................................... 113 6.2 Installatiehandleiding Windows ............................................................................. 120 6.3 Installatiehandleiding Linux ................................................................................... 120 7 Conclusies ...................................................................................................................... 121 8 Kritische Reflectie ........................................................................................................ 123 9 Voor akkoord verklaard .............................................................................................. 124 10 Literatuurlijst ............................................................................................................... 125 10.1 10.2 Boeken .................................................................................................................... 125 Webpagina’s ........................................................................................................... 125 11 Bijlagen .......................................................................................................................... 126 11.1 11.2 11.3 11.4 Installatie onder Windows ...................................................................................... 126 Installatie onder Linux ........................................................................................... 146 Actierapport ............................................................................................................ 162 Functiebeschrijving rapport.................................................................................... 164 1 Voorstelling van het bedrijf Dolmen is een informaticadienstverlener die inmiddels reeds meer dan 20 jaar actief is op de Belgische markt. Ongeveer 850 medewerkers realiseren er samen een omzet van 138 miljoen euro. Als toonaangevend informaticabedrijf is het voor vele organisaties uit diverse sectoren de vaste hard- en softwarepartner geworden. Ontsproten in de schoot van Colruyt heeft het bedrijf gedurende heel haar bestaan een maturiteit en stabiliteit opgebouwd die zich ondermeer vertaalt in een duidelijke missie en een set van corporate values waar elke werknemer van Dolmen zich naar spiegelt. De missie, waarden en historiek bepalen Dolmens herkenbare bedrijfscultuur. Dolmens producten en diensten situeren zich binnen tal van informaticadomeinen. De focus ligt op het aanbieden van geïntegreerde totaaloplossingen op basis van de noden van de klant. Dit zowel op infrastructureel als op applicatiegebied. Dolmen telt 7 vestigingen Corporate Headquarter Industriezone Zenneveld A. Vaucampslaan 42 1654 Huizingen Dolmen Brussel Bruidstraat 11 1000 Brussel Dolmen De Pinte Grote Steenweg 15 9840 De Pinte Dolmen Harelbeke Kortrijksesteenweg 307 8530 Harelbeke Dolmen Kontich Veldkant 33B 2550 Kontich Dolmen Namur Rue de Gembloux 9A 5080 Rhisnes Dolmen Turnhout Steenweg op Mol 148 2360 Oud-Turnhout Eindwerk Bram Gadeyne 2007-2008 12 In 2 van deze vestigingen, namelijk in De Pinte en in Huizingen (Corporate Headquarters), liep ik stage. Dolmen De Pinte Dolmen Huizingen Dolmen levert een groot aantal diensten die allen kunnen gevraagd worden door de klant. Daarnaast levert Dolmen ook totaaloplossingen waarbij ze op allerlei domeinen een zo goed mogelijke uitwerking van de vraag proberen te verzekeren. In onderstaande figuur kun je alle services terugvinden. Ze zijn weergegeven op 2 assen die ze in verschillende domeinen opdeelt. • • de horizontale as: o Projects zijn eenmalig en bepaald in de tijd, met een vaste begin- en einddatum o Exploitation, ook de ‘Managed Services’ genoemd, is een continu proces de verticale as: o Tactical omvat het sturende o Operational duidt op het uitvoerende schema services Dolmen biedt 3 grote groepen services aan. • • • Eindwerk Bram Gadeyne 2007-2008 Applications Services Education Services Infrastructure Services 13 2 Stageopdracht De stageopdracht waarvoor ik solliciteerde legde sterk de nadruk op het idee van Web 2.0. Dit is weliswaar geen term die een echte betekenis heeft. Web 2.0 houdt eigenlijk in dat webapplicaties evolueren naar applicaties die eerder lijken op gewone desktop applicaties waarbij webpagina’s niet moeten herladen worden om extra onderdelen van de applicatie op te roepen. De opdracht bestond er in een nieuw framework te onderzoeken genaamd Seam. Dit java framework is gebaseerd op enkele java standaarden. Het is naast het dichter brengen van het idee van web 2.0 ook de bedoeling van Seam om meer standaarden opnieuw te gebruiken en een goede integratie ertussen te voorzien. De integratie van web 2.0 zal vooral gebeuren door het gebruik van AJAX. Dit is de afkorting van “Asynchronous JavaScript and XML” en maakt het mogelijk om stukken HTML code te vervangen zonder daarvoor de pagina opnieuw te moeten laden. Hiervoor maakt Seam ook weer gebruik van frameworks waaronder het Richfaces framework. Dit maakt het mogelijk om rich internet applications te maken. Deze technische analyse zette ik dan om naar de praktijk door een competentie management system te maken. Momenteel worden competenties van medewerkers en functiebeschrijvingen bijgehouden bij de chefs op papier. Men wil hier echter een geautomatiseerde applicatie voor gebruiken zodat deze registraties allemaal ongeveer gelijk worden bijgehouden en digitaal kunnen worden opgeslagen. Omdat de stageopdracht vooral over de technische analyse ging kreeg ik van Dolmen een funcionele analyse. Deze analyse heb ik in de loop van het programmeren van de webapplicatie deels aangepast. Het analysedossier droeg de naam “Project ComMaS” wat een afkorting is voor Competence Management System. ComMaS is dan ook de naam die het uiteindelijke programma gekregen heeft. Eindwerk Bram Gadeyne 2007-2008 14 3 Analyse Onder dit hoofdstuk vind je een stuk terug uit de functionele analyse die ik ontving van Dolmen. Dit zou je een overzicht moeten geven van wat er van de uiteindelijke applicatie precies verwacht werd. Sommige onderdelen van de analyse heb ik tijdens mijn stage wat bijgestuurd en deze worden dan ook toegelicht. 3.1 Doelstelling Naast de technische analyse die ik moest uitvoeren, was er ook het omzetten van deze functionele analyse in de praktijk. De competence management applicatie die ik hiervoor ontwikkelde had een aantal doelstellingen voor de onderneming. • Een competentere medewerker. Medewerkers kunnen competenties verwerven aan de hand van de vraag van klanten of aan de hand van persoonlijke voorkeuren om bijvoorbeeld verder te kunnen groeien in de onderneming. Als we een overzicht hebben van de huidige competenties kunnen we sneller en beter de medewerker competenter maken om aan deze vragen te voldoen. • Een betere opvolging wie welke opleiding volgde. Opleidingen die door Dolmen georganiseerd worden moeten kunnen worden weergegeven en gebruikers moeten er kunnen toegevoegd worden aan sessies. Op die manier is er altijd een overzicht van wie waar en wanneer welke opleiding in het verleden volgde of in de toekomst zal volgen. • Beheer van de actieplannen. Medewerkers binnen Dolmen hebben een actie plan die acties bevat om bijvoorbeeld competenties te verwerven. Deze acties moeten digitaal beschikbaar gemaakt worden. o Mogelijkheid tot aanvullen van de competentiefiches met extra competenties. Competentiefiches bevatten verzamelingen van competenties en moeten dus kunnen worden uitgebreid indien nodig. 3.2 Bestaande situatie Voor alle verschillende functies binnen Dolmen bestaan er functiebeschrijvingen. Deze functiebeschrijving omvat de hoofdtaken, plaats in de organisatie en de nodige competenties. Competenties zijn op te splitsen in technische competenties (kennen, bvb J2EE) en gedragscompetenties (kunnen, bvb klantgerichtheid). Bij competentiemanagement is het de bedoeling om mensen te laten groeien en evolueren. Tijdens een persoonlijk onderhoud wordt de eigen competentie afgewogen ten opzichte van het functieprofiel. Vanuit deze evaluatie wordt gekeken waar er eventueel tekortkomingen zitten en waar er bijsturingen en evoluties dienen te gebeuren. Ook het doorgroeien naar andere profielen wordt op deze manier georganiseerd. (interne jobrotatie) Indien er bijsturingen noodzakelijk zijn kunnen er opleidingen worden gevolgd, coaching georganiseerd en/of learning on the job worden toegepast. Er zijn interne en externe opleidingen, Eindwerk Bram Gadeyne 2007-2008 15 georganiseerd door de chef zelf, door educ en door HR. Er zijn technische trainingen, vaardigheidstrainingen en persoonlijke groeitrainingen. Sommige van deze trainingen worden in eigen tijd andere in betaalde tijd gevolgd. Van sommige opleidingen bestaan evaluaties en actieplannen voor follow up. Er kunnen tevens certificaten gehaald worden op het einde van sommige opleidingen. De competentieprofielen zelf worden door de personeelsdienst beheerd in nauw overleg met de betrokken chefs. De huidige manier van werken is volledig uitgeschreven in ISO procedures. De gebruikte ISO procedures: • • • • • • PS-DOCB-ALG-004 (Beheersproces competence management) PR-OPBY-ALG-004 (Persoonlijk onderhoud) PR-DOCB-ALG-003 (Beheer competenties) PR-OPLI-ALG-002 (Opleiding) PR-OPLI-ALG-001 (Opleiding van medewerkers) Voorbeelden van competentiefiches en functiebeschrijvingen Er zijn een aantal problemen met de huidige manier van werken: 1. 2. 3. 4. 3.3 Geen eenduidige plaats waar iemands competentieprofiel wordt bijgehouden Geen opvolging van groei en evolutie van de medewerker Geen overzicht van wie welke opleidingen gevolgd heeft Geen eenvoudige opvolging van de actieplannen in het kader van competentie management mogelijk Functionele eisen • • • • • • Beheer competenties o Er moet een overzicht bijgehouden worden van alle competenties die functiebeschrijving, een opleiding of een medewerker kan bevatten. Deze lijst van competenties moet kunnen worden aangepast. Beheer functiebeschrijvingen en –profielen o Functiebeschrijvingen moeten in een centrale plaats kunnen worden beheert zodat elke functie in het programma dezelfde betekenis heeft. Beheer opleidingen o Dolmen organiseert opleidingen die moeten kunnen weergegeven worden en waarvoor medewerkers moeten kunnen ingeschreven worden. Medewerkers kunnen ook opleidingen volgens buiten Dolmen die dan ook weer moeten kunnen worden bijgehouden. Beheer acties o Actieplannen van medewerkers moeten kunnen worden bijgehouden. Beheer PO verslagen o PO staat voor persoonlijk overleg. Van alle persoonlijke overleggen tussen chef en medewerker moet er een verslag kunnen worden bijgehouden. Beheer klantentevredenheidsonderzoeken Eindwerk Bram Gadeyne 2007-2008 16 o Een chef kan na een project van een klant een klantentevredenheidsonderzoek ontvangen. Die kunnen worden bijgehouden bij de medewerker die aan dit project meewerkte ter referentie. Niet-functionele eisen 3.4 • • • • • 3.5 Randvoorwaarden • • • • 3.6 Gebruiksvriendelijke interface Informatie eenvoudig te raadplegen Beperkte offline mogelijkheden. Dienen offline te kunnen worden geraadpleegd: Compententiefiche, Actieplan, PO verslagen, Klantentevredenheidsonderzoeken, Functieprofielen, Gevolgde opleidingen (allemaal in functie van een PO). Er moet snel aan actieplannen kunnen gewerkt worden De taal van de applicatie moet volgens Dolmen-standaarden gerealiseerd worden. De applicatie wordt in het Engels opgebouwd, maar de velden kunnen in het Nederlands en Frans worden weergegeven. De personeelsdatabank is een Oracledatabank. De servers van Dolmen werken met Windows 2003. De applicatie zal moeten werken via de Portal van Dolmen (ook via Windows 2003) De applicatie kan gebruik maken van de Single Sign-on van de Portal. Use case diagrams In de Functionele analyse die ik ontving van dolmen waren alle use cases en use case diagrams gegeven. Deze heb ik dan ook zo goed mogelijk proberen te integreren in mijn applicatie. Hieronder vind je een overzicht terug van de use case diagrams die in de analyse terug te vinden waren om een idee te krijgen van de scope van de applicatie. De Use Cases zelf heb ik niet opgenomen in dit stageverslag omdat dit niet in de scope van dit verslag thuishoort. Eindwerk Bram Gadeyne 2007-2008 17 uc Use Case model Beheer Functiebeschrijving PersVA Beheer Competentiefiche Chef Beheer actieplan CVappl Medewerker Beheer opleiding PersSec 3.6.1 Beheer Competentiefiche Het beheer van de competentiefiches is waarschijnlijk het belangrijkste onderdeel van de applicatie. Dit houdt alle functionaliteiten in die te maken hebben met de relatie tussen Chef en medewerker. Het beheer van de competenties per medewerker wordt hierin voorzien, samen met het invoeren van de PO verslagen en de klantentevredenhedenheidsonderzoeken. Eindwerk Bram Gadeyne 2007-2008 18 uc Use Case Beheer Competentiefiche Bewerk Functie In Competentiefiche Chef Voeg Competentie Toe Aan Competentiefiche Toevoegen klantentevredenheid Vul Competentiefiche In Voer PO verslag in Bewerk KlantenTevredenheidsonderzoeken Bewerk PO verslag Medewerker 3.6.2 Beheer Opleiding Opleidingen voor medewerkers zijn opgesplitst in 2 grote groepen. Een medewerker kan opleidingen volgens in zijn vrije tijd. Daarnaast voorziet Dolmen echter ook zelf opleidingen om zijn medewerkers bij te scholen. Het beheer van deze opleidingen wordt door deze use case diagram aangegeven. Eindwerk Bram Gadeyne 2007-2008 19 uc Beheer opleiding Voeg Eigen Opleiding Toe Medewerker Toevoegen Opleiding Chef Toevoegen Medewerker aan opleidingssessie PersSec 3.6.3 Beheer Actieplan Het opstellen van acties binnen de applicatie is beschikbaar met als doel om aandachtspunten voor de toekomst niet uit het oog te verliezen. Elke actie heeft een deadline voor uitvoering ervan. Een actie kan bijvoorbeeld het resultaat zijn van een aantal besproken punten in een persoonlijk overleg tussen een chef en een medewerker. Eindwerk Bram Gadeyne 2007-2008 20 uc Beheer actieplan Medewerker Chef Aanmaken acties Bewerken acties PersVA 3.6.4 Beheer Functiebeschrijving De functiebeschrijvingen bestaan uit 2 delen. Het ene deel omvat de beschrijving zelf waarin de talen van een bepaalde functie worden opgegeven. Daarnaast is er nog een functieprofiel die bij een functiebeschrijving hoort. In dit profiel worden de competenties waarover een medewerker moet beschikken weergegeven. Tijdens een PO kunnen medewerker en chef dan bekijken of een bepaalde medewerker aan de richtlijnen van een bepaalde functie zou voldoen of welke competenties die nog moet verwerven alvorens dit mogelijk is. Dit is dus vooral bedoeld om het doorgroeien binnen Dolmen af te kunnen stellen op de noden en eisen van de medewerker zelf. Eindwerk Bram Gadeyne 2007-2008 21 uc Use Case Beheer Functiebeschrijving Creëer Functiebeschrijving PersVA Bewerk Functiebeschrijving Creëer Competentie Bewerk Functieprofiel Ken Score Toe Chef 3.7 Rapporten Naast het bijhouden van de informatie in het systeem moest het ook mogelijk zijn om een aantal rapporten te genereren die dan konden worden afgeprint. Een aantal voorbeelden van rapporten zijn terug te vinden in de bijlagen. Dit is nodig voor volgende onderdelen: • • • • • 3.8 Competentiefiches van medewerkers Actielijsten Lijsten van gevolgde opleidingen van een medewerker PO verslagen van een medewerker Functieprofielen Beschrijving gebruikers Van het systeem moesten enkele gebruikersgroepen gebruik kunnen maken. Deze gebruikers zijn ook terug te vinden op de use case diagrams. De beschrijving van deze gebruikersgroepen wordt hier wat meer toegelicht. Eindwerk Bram Gadeyne 2007-2008 22 3.8.1 Personeelsverantwoordelijke Een personeelsverantwoordelijke heeft toegang tot alle documenten met betrekking tot competentiebeheer. Hij kan tevens een aantal zaken doen. Zo kan een personeelverantwoordelijke enkele acties aanmaken en bewerken in het actieplan van een medewerker. Net als een chef kan hij een functieprofiel bewerken. Een personeelsverantwoordelijke is verantwoordelijk voor het opstellen van een functiebeschrijving en een functieprofiel. Hij kan ook als enige een functiebeschrijving bewerken. 3.8.2 Personeelssecretariaat Het personeelssecretariaat voegt opleidingen toe die georganiseerd worden door de HR afdeling. Daarnaast kan ook het personeelssecretariaat mensen inschrijven voor opleidingen. 3.8.3 Chef De chef is verantwoordelijk voor heel wat zaken binnen de applicatie. De chef is de meest betrokken gebruiker van het systeem. Hij beheert de competentiefiches en actieplannen van zijn medewerkers. Hij is tevens betrokken bij het opstellen en beheren van de functiebeschrijvingen (in samenspraak met de personeelsverantwoordelijke). De chef is ook verantwoordelijke voor het toekennen van de scores aan de functieprofielen. 3.8.4 Medewerker Een medewerker kan acties toevoegen en beheren aan zijn actieplan. Bij het klantentevredenheidsonderzoek en het PO (persoonlijk overleg) verslag, is er een mogelijkheid voorzien waarin de medewerker opmerkingen kwijt kan over de documenten. 3.9 Rechten gebruikers Binnen de ComMaS (Competence Management System) applicatie zal de hiërarchie van Dolmen gerespecteerd worden. Elke actie die een medewerker kan uitvoeren is ook beschikbaar voor zijn directe chef. Iedereen die hoger in de hiërarchie staat kan alles wat de gebruikers onder hem kunnen. Daarnaast kunnen ook de personeelsverantwoordelijken alles uitvoeren voor alle medewerkers. Bij het toevoegen van medewerkers aan opleidingssessies kunnen ook chefs die in dezelfde afdeling zitten medewerkers selecteren van andere chefs. Eindwerk Bram Gadeyne 2007-2008 23 4 Ontwerp 4.1 Logisch Een datamodel was gegeven in de analyse van Dolmen. Helaas was dit model nog niet volledig. Bij de functionele analyse zaten al schermen die de applicatie beschreven en toonden hoe men verwachtte dat deze er ongeveer uit zouden gaan zien. Om sommige schermen te maken of extra functionaliteiten toe te voegen heb ik soms het datamodel moeten aanpassen. Ik heb in het begin van mijn stage al deze schermen overlopen om te controleren of alle gevraagde gegevens wel degelijk in het gegeven datamodel aanwezig waren. Meestal was een scherm een lijst of detail weergave van een bepaalde database tabel. Op die manier kon ik gemakkelijk velden toevoegen op deze locaties in het datamodel. Meestal ging het hier dan over boolean veldjes die “vergeten” waren in het datamodel. Dit gebeurde volgens het principe van ER waarbij ik me de vraag stelde of een bepaald veld een relatie had met de tabel (entity). Bijvoorbeeld “een medewerker heeft een username”. Op sommige plaatsen heb ik ook een tussentabel toegevoegd. Dit gebeurde op plaatsen waar er een veel op veel relatie beschreven stond. In de praktijk moet men ook steeds een tussentabel voorzien in de effectieve databank op veel op veel locaties. Op die plaatsen bleek bij de analyse van de schermen dat er soms ook nog extra informatie nodig was en dat die in deze tussentabellen het beste thuis hoorde. Voorbeelden van extra tussentabellen zijn de tabellen competf_fbeschrijving waar een status aan toegevoegd werd en de tabel opleiding_competentie waar geen extra informatie nodig was. In sommige tabellen was er nood aan een extra boolean veldje om waarden van checkboxen in op te slaan. Bij het toevoegen van extra functionaliteiten heb ik ook een aantal aanpassingen in het datamodel moeten doen. Een voorbeeld was de mogelijkheid voor het verzenden van een herinnering voor deadlines van acties via mail. Hiervoor moest ik beschikken over een e-mailadres in de tabel medewerker en een boolean veldje in de tabel actie om aan te geven of een herinnering al dan niet al verzonden werd. Een overzicht van het uiteindelijke datamodel met de types van de velden vind je hierna in het schema van het datamodel. Eindwerk Bram Gadeyne 2007-2008 24 4.1.1 Data-analyse / Datamodel Eindwerk Bram Gadeyne 2007-2008 25 4.1.2 Objectgeoriënteerd model Van alle tabellen weergegeven in het datamodel werd een overeenkomstige entity klasse opgesteld. Een entity klasse is een object georiënteerde weergave van een tabel die als object 1 rij uit de overeenkomstige tabel zal voorstellen. Het bestaat meestal uit een gewone klasse die alle velden met een overeenkomstige waarde voorziet van getters en setters. Meer informatie over entitys is terug te vinden bij het hoofdstuk over persistence. Voor elk van deze entity klassen werd dan een actie, service en DAO object opgesteld zoals dit beschreven staat in de architectuur die ik gebruikte. Meer informatie over deze opstelling en wat de functie is van deze klassen kun je terugvinden bij het hoofdstuk over de architectuur van de applicatie. Over de DAO’s waarover hier sprake is kunnen we toch al het één en ander verduidelijken. Ze zijn opgebouwd in een specifieke hiërarchie die niet echt technologie onafhankelijk is. De code voorbeelden zijn wel in Java uitgeschreven. 4.1.2.1 Generic DAO’s Elke entity klasse beschikt over een overeenkomstige DAO (data access object). Elke DAO weet perfect hoe hij voor zijn eigen entity type een aantal acties kan uitvoeren. Deze acties hebben allemaal betrekking op een datasource zoals bijvoorbeeld een database. De DAO weet hoe hij deze datasource kan raadplegen. Sommige acties waarin een DAO voorziet zijn voor alle DAO’s gelijk. Andere acties zijn dan weer specifiek voor een bepaalde entity. Dankzij het gebruik van generics kunnen we een basis DAO maken die alle basisfunctionaliteiten abstract beschrijft. Een generic maakt het mogelijk om af te dwingen dat een object van een bepaald (abstract) type is. In ons geval gebruiken we de abstracte generic waarde T en de abstracte generic waarde ID. T dwingt daarbij af dat een bepaald object een entity klasse is. ID vraagt in welk objecttype de ID van deze entity klasse opgeslagen is. Een overzicht van de basis functionaliteiten van een DAO zijn terug te vinden in de onderstaande interface. Zoals je kan zien worden de generics meegegeven aan de klasse en kunnen die dan abstract gebruikt worden in de beschrijving van de methoden. Alle entitys zijn immers van het type T en alle id objecten zijn van het type ID. Eindwerk Bram Gadeyne 2007-2008 26 public interface IDAO<T, ID extends Serializable> { T findById(ID id, boolean lock); List<T> findAll(); List<T> findByExample(T exampleInstance, String... excludeProperty); T makePersistent(T entity); T insert(T entity); void makeTransient(T entity); @PersistenceContext(unitName = "ProjectCommasPU") public void setEntityManager(EntityManager em); public EntityManager getEntityManager(); } Van deze interface maakte ik dan een abstracte klasse baseDAO. Deze abstracte klasse implementeert alle methoden die beschreven zijn in de IDAO interface. Het voorziet ook in een connectie tot een bepaalde datasource. Op die manier zullen alle afgeleide DAO’s gebruik maken van dezelfde datasource. Hier wordt gebruik gemaakt van een EntityManager als datasource maar andere datasources kunnen evengoed gebruikt worden. Meer uitleg over de EntityManager en de Persistence Context kun je terugvinden in het hoofdstuk over Persistence. Nu werd voor elk entitytype ook weer een interface beschreven van een DAO die afgeleid is van de IDAO interface. In deze interface werden dan methoden beschreven die specifiek voor deze DAO van belang zijn. Een voorbeeld van een interface van een generic DAO voor het entity object Action: public interface IActieDAO<T, ID extends Serializable> extends IDAO<T, ID> { List<T> getByMedewerker(Medewerker medewerker); List<T> getAllNotMailed(); } Van deze interface werd dan ook weer een nieuwe klasse afgeleid. Ditmaal echter geen abstracte maar een echte klasse. Deze klasse kan gebruik maken van de functionaliteiten in de baseDAO en heeft dan ook toegang tot de datasource. Een voorbeeld van een generic DAO voor het entity object Action. De uitwerking hiervan is opgemaakt in Java code en maakt gebruik van een entityManager en HQL (een SQL soortgelijke taal om te gebruiken met Hibernate) Meer informatie over de EntityManager en Hibernate zijn te vinden bij het hoofdstuk over Persistence en Hibernate. Eindwerk Bram Gadeyne 2007-2008 27 public class ActieDAO extends BaseDAO<Actie, Long> implements IActieDAO<Actie, Long> { @SuppressWarnings("unchecked") public List<Actie> getByMedewerker(Medewerker medewerker) { List<Actie> lijst; try { lijst = getEntityManager() .createQuery( "from Actie as a where a.medewerkerid=?1 order by a.status, a.deadline") .setParameter(1, medewerker).getResultList(); } catch (RuntimeException e) { lijst = new ArrayList<Actie>(); } return lijst; } @SuppressWarnings("unchecked") public List<Actie> getAllNotMailed() { List<Actie> lijst; try { lijst = getEntityManager() .createQuery( "from Actie as a where a.mailed = 'N'").getResultList(); } catch (RuntimeException e) { lijst = new ArrayList<Actie>(); } return lijst; } } 4.1.2.2 Klassen Hiërarchie Het schema van de Generic DAO’s kan hieronder teruggevonden worden. Bovenaan vinden we de IDAO terug en de abstracte BaseDAO waarvan respectievelijk de Interfaces en de uiteindelijke DAO’s zijn afgeleid. Meer informatie over Generic DAO’s kun je in het hoodstukje over Generic DAO’s terugvinden. Naast de Generic DAO’s zijn ook de acties op een soortgelijke manier opgebouwd via een IAction interface die alle basis acties van een Actie beschrijft en een abstracte klasse ListAction die de basisfunctionaliteit voor lijsten voorziet. Eindwerk Bram Gadeyne 2007-2008 28 Eindwerk Bram Gadeyne 2007-2008 29 4.2 Architectuur Voor de uitwerking van mijn stageopdracht raadde men me aan om gebruik te maken van een gelaagd model. Een gelaagd model heeft als voordelen dat elke laag precies weet wat het moet doen en dat objecten uit verschillende lagen loosely coupled van elkaar gebruik kunnen maken. Meer uitleg over de gebruikte architectuur kun je hieronder terugvinden. 4.2.1 Application Architecture Deze Architectuur bestaat uit 5 lagen die telkens samen kunnen werken met de laag boven of onder hen. Tussen alle lagen door kunnen Entity objecten gebruikt worden om gegevens door te geven. Meer uitleg over de verschillende lagen en hun functies zijn terug te vinden in onderstaande tabel. Laag Presentation Layer Uitleg Deze bevat alle webpagina’s. In het geval van mijn Seam project zijn dit JSF en Richfaces pagina’s. Ook pagina’s voor mail rendering, statische html pagina’s, JSP pagina’s, enz. worden hier gelokaliseerd. De Presentation layer op zich heeft enkel de functie iets weer te geven. Het afhandelen van acties of bewerkingen worden dan door de onderliggende lagen opgeroepen of uitgevoerd. Application Layer De presentation layer wordt gebonden (binding) aan bepaalde acties. Meestal gaat het hier om een druk op de knop die een bepaalde actie uitvoert of een listener die aan een bepaalde control is gebonden. Acties worden meestal doorgegeven aan de service laag. In deze laag houdt men ook objecten bij die een bepaalde status kunnen onthouden. Op die manier kunnen we de view opnieuw opbouwen aan de hand van de vorige status. Lijsten kunnen worden omgezet naar lijsten die begrijpbaar zijn door de presentation layer. Service Layer De business logica zoals berekeningen worden hier afgehandeld. Als een service gegevens moet wegschrijven in een database of gegevens nodig heeft dan zal hij die opdracht doorgeven aan een DAO. Eigenlijk gaat het hier dus vooral om logica die moet worden uitgevoerd en waarbij geen afhankelijkheid bestaat van de view die wordt gebruikt. Op die manier kan aan elke applicatie een andere view methode worden gekoppeld zoals Swing voor een desktopapplicatie en JSF voor een webapplicatie. Data Access Layer In deze layer bevinden zich DAO’s. Deze hebben alle kennis in verband met (DAO’s) een bepaalde tabel uit de database en weten hoe ze bepaalde handelingen op de database via een JPA(in mijn project Hibernate) kunnen uitvoeren. DAO’s worden meestal opgebouwd via Generics omdat de basisfunctionaliteit bij elke DAO dezelfde blijft. Alleen kunnen extra methoden voor sommigen DAO’s gewenst zijn. Eindwerk Bram Gadeyne 2007-2008 30 Model Tussen alle lagen door worden objecten doorgegeven. Meestal gaat het hier over entities of collecties van entities. Deze zijn dan ook beschikbaar in alle lagen. Het is echter enkel de DAO laag die de entities ook effectief kan ophalen of wegschrijven naar een databank. Dankzij deze architectuur kan men in theorie heel gemakkelijk een andere database aan een bepaalde applicatie koppelen of een andere presentatie techniek zoals swing ipv web gebruiken. Elke laag is loosely coupled wat wil zeggen dat ze zich eigenlijk niet moeten bezighouden met hoe de laag boven of onder zich werkt. Wel moeten ze weten hoe ze kunnen communiceren met andere lagen. Ook onderhoud van de applicatie kan gemakkelijk gebeuren. Er kan gedelegeerd worden wie wijzigingen moet aanbrengen in welke laag zonder dat die wijzigingen gevolgen hebben in de rest van de applicatie. Testen kunnen dan ook gemakkelijk worden geschreven per laag om te waarborgen dat een laag nooit een andere laag zal beïnvloeden. 4.2.2 Platformonafhankelijkheid Voor de ondersteuning van platformonafhankelijkheid heb ik gebruik gemaakt van een propertie file. Hierin heb ik alle verwijzingen naar paden en enkele andere eigenschappen opgeslagen Eindwerk Bram Gadeyne 2007-2008 31 waardoor deze kunnen worden aangepast buiten de applicatie. Java op zich is platformonafhankelijk want elke Java file kan worden begrepen door de JVM die per platform installeerbaar of compileerbaar is. De verwijzingen naar paden op een bepaald bestandssysteem kunnen ervoor zorgen dat code van de applicatie niet platformonafhankelijk werkt. Een TimerTask zorgt ervoor dat opties kunnen worden aangepast terwijl de server in werking is en zonder dat deze moet worden herstart om de wijzigingen van kracht te laten worden. Een TimerTask start een Thread die volgens een bepaalde frequentie een bepaalde methode zal uitvoeren. /** * Een Timertask die het options.properties bestand inleest volgens het interval * zoals aangegeven in de options.properties file. * */ private class TimerTaskImpl extends TimerTask { @Override public void run() { InputStream stream = loader .getResourceAsStream("options.properties"); try { synchronized (properties) { properties.load(stream); } System.out.print("timertask uitgevoerd."); } catch (IOException e) { System.out.print("kon properties niet lezen." + e.getMessage()); } catch (RuntimeException e) { System.out.print("kon properties niet lezen." + e.getMessage()); } } } 4.3 Technisch De technische analyse nam de grootste tijd van mijn stage in beslag. De doelstelling was om uiteindelijk het Seam framework te leren gebruiken en er de toepasbaarheid van uit te testen. Om Seam echter te begrijpen moest ik eerst een kijkje nemen naar enkele andere frameworks waarop Seam gebaseerd is. JSF en EJB 3.0, die verder nog worden uitgelegd, zijn hiervoor de belangrijkste. Ook maakt Seam gebruik van Java 5 wat een aantal voordelen met zich meebrengt. Naast deze frameworks waren er ook nog andere frameworks die extra functionaliteiten voorzien. Deze worden door Seam ook geïntegreerd in de vorm van componenten. Deze onderstaande figuur kan u een idee geven over het doel van de verschillende frameworks in het geheel. Seam zorgt voor een goede integratie tussen JSF en EJB 3.0. Seam voorziet dankzij EJB 3.0 in allerlei componenten die een bepaalde functionaliteit aanbieden. Deze componenten zijn gebaseerd op frameworks die hun kunnen al meerdere malen bewezen hebben. In de volgende hoofdstukken geef ik meer uitleg over de verschillende frameworks. Eindwerk Bram Gadeyne 2007-2008 32 4.3.1 Java 5 Hoewel de nieuwste versie van Java versie 6 is maakt Seam gebruik van Java 5. Dit brengt een aantal belangrijke nieuwigheden met zich mee, waaronder annotaties en generics die het leven van de programmeur heel wat aangenamer maakt. 4.3.1.1 Annotaties Annotaties kennen veel voor- en tegenstanders. Configuratie gebeurt door velen in XML bestanden. Die zijn gemakkelijk toegankelijk en ze zijn gegroepeerd in een aantal bestanden op een vaste locatie. Het probleem met deze XML configuratie is dat men soms het gevoel heeft dat men programmeert in XML en niet langer in Java. Hiervoor heeft Java 5 de nieuwe mogelijkheid genaamd annotaties geïntroduceerd. Annotaties brengen configuratie die vroeger in XML bestanden stonden terug naar de code. Naast configuratie bieden annotaties ook nog de mogelijkheid om in geannoteerde objecten een bepaald object te injecteren. Annotaties worden at runtime geïnterpreteerd waardoor sommige servers soms anders reageren op bepaalde annotaties dan andere. Annotaties zijn gemakkelijk te herkennen in de code omdat ze altijd met het @ symbool beginnen. 4.3.1.2 Generics Generics is ook één van de nieuwigheden die men in Java 5 heeft geïntroduceerd. Ze maken het mogelijk om op bepaalde plaatsen af te dwingen dat de te gebruiken objecten van een bepaald (abstract) type zijn. Bij het hoofdstuk over Generic DAO’s vind je een voorbeeld terug over de abstracte generics notatie T en ID. Generics zijn gemakkelijk te herkennen omdat ze altijd tussen “<” en “>” symbolen staan. Eindwerk Bram Gadeyne 2007-2008 33 Een voorbeeld met een generic List: List<Actie> actieLijst=new ArrayList<Actie(); actieLijst kan opgevuld worden met een lijst. In deze lijst mogen echter alleen objecten zitten van het supertype Actie. 4.3.2 EJB 3.0 De Enterprise JavaBeans-specificatie is één van de Java-APIs in de J2EE-standaard. EJB's zijn bedoeld om in een meerlagenmodel de zogenaamde businesslogica van een applicatie te bevatten. In mijn applicatie rijken ze over de Application, Service en Data Access Layer. Deze lagen bevatten immers de business logica van de applicatie. Een Enterprise Java Bean bestaat uit een klasse waarvan objecten worden beheerd door een zogenaamde EJB container. Deze container zal instanties van de objecten aanmaken, bewaren en vernietigen wanneer dit nodig is. Objecten kunnen dan aan deze EJB container worden opgevraagd om er bepaalde bewerkingen mee uit te werken. EJB’s worden tijdelijk opgeslagen in de session scope. Een scope laat toe om Beans, objecten of variabelen op te slaan gedurende een bepaalde tijd die de scope omvat. De session als voorbeeld van een scope beschrijft dan meestal de periode tussen het aan en afmelden van een bepaalde gebruiker. We onderscheiden 2 soorten Session EJB’s. De Stateless Beans en de Stateful Beans. 4.3.2.1 Stateless Bij Stateless Session Beans wordt een instantie van de Bean aangemaakt wanneer deze wordt opgevraagd. Bij het aanmaken hiervan worden de dependencys geïnjecteerd en worden eventueel methoden uigevoerd die met de annotatie @PostConstruct gedefinieerd zijn. Dependencys zijn andere EJB’s die aan de te initialiseren EJB moeten worden gekoppeld en waarvan deze EJB afhankelijk is. Dit gebeurt aan de hand van een techniek die Injection wordt genoemd. Wanneer een Stateless Session Bean door de garbage collector verwijderd wordt, dan wordt bij het opnieuw opvragen van deze Session Bean gewoon een nieuwe instantie teruggegeven. In een Stateless Session Bean kun je dus in principe geen status opslaan over een lange periode omdat je nooit weet of een Bean dezelfde is als de vorige. Eindwerk Bram Gadeyne 2007-2008 34 4.3.2.2 Stateful Bij de Stateful Session Bean kun je in tegenstelling tot de Stateless wel een status opslaan. Een Bean die een eindje niet gebruikt wordt, wordt dan passief gemaakt. Via de 2 methoden die met de 2 annotaties @Remove en @Predestroy geannoteerd zijn kun je nog enkele zaken laten uitvoeren alvorens deze Bean passief wordt gemaakt. Als men deze Bean opnieuw opvraagt dan wordt de Bean opnieuw actief gemaakt en kun je dus verder werken met dezelfde Bean. Stateful Session Beans belasten hierdoor het systeem wel meer dan Stateless Session Beans. 4.3.2.3 Gebruik Een EJB bestaat steeds uit minimum 2 klassen. Een interface die de @Local annotatie gebruikt en een daarvan afgeleide klasse die dan de invulling van de EJB bevat. Dit is eigenlijk omdat EJB werkt volgens het systeem van RMI. Een EJB wordt opgezocht via zijn JNDI naam (Java Naming and Directory Interface). JNDI geeft je dan een Proxy (stub) terug die de interface van de EJB implementeert en die met de effectieve (lokale) EJB kan praten. JNDI maakt het mogelijk om objecten via hun opgegeven naam op te zoeken in een bepaald register. Onderstaand voorbeeld toont hoe de werking van RMI in elkaar zit. Er wordt van een bepaalde klasse een implementatie gemaakt en een interface. Van deze implementatie zal dan een Stub object worden gegenereerd. Dit stub object wordt in een register geplaatst die via JNDI geraadpleegd kan worden. De client kent de interface van het object die hij op de server zou willen raadplegen. Hij vraagt de Stub, die dezelfde interface geïmplementeerd heeft, op aan het register via de JNDI-naam van dit object. Nu kan de client door zijn interface via de stub communiceren met de stub aan de server kant die op zijn beurt dan communiceren met het effectieve object op de server. Voor de client lijkt het alsof het object op de client zelf zou Eindwerk Bram Gadeyne 2007-2008 35 aanwezig zijn. Natuurlijk hoeft de client hier niet een effectieve andere computer te zijn maar kan dit ook binnen dezelfde computer gebruikt worden. In een standaard Java applicatie wordt er gebruik gemaakt van RMI om een EJB via zijn Proxy op te halen uit een EJB Container. Dit lijkt misschien omslachtig maar dit blijkt nodig te zijn als we met injecties willen werken. Dankzij injecties kunnen we vanuit de ene EJB A een andere EJB B raadplegen zonder dat de A precies weet met welke B hij communiceert. Zo moet A ook niet weten of B een statefull of stateless bean is. Wel moet B zeker dezelfde interface gebruiken als die van zijn Proxy. Een injectie hierbij is het opzoeken van een bepaalde stub in het JNDI register en deze koppelen aan een interface die men wil gebruiken in een de EJB. Natuurlijk kunnen we dan ook EJB Containers gaan raadplegen vanuit verschillende servers. Op die manier kunnen we dan weer functionaliteit, verantwoordelijkheden en processing time Eindwerk Bram Gadeyne 2007-2008 36 balanceren over verschillende servers. Dit systeem heb ik natuurlijk niet toegepast op mijn stage maar kan eventueel bij hele grote en zware applicaties worden gebruikt. 4.3.3 JSF Java Server Faces is een onderdeel van Java EE (Enterprise Edition) en voorziet in een makkelijke conversatie tussen de view (JSP) en de business laag (bijvoorbeeld java beans of EJB’s). Via een speciale EL (Expression Language) kunnen bepaalde actions (methoden) gemakkelijk gebonden (binding) worden aan business acties en kunnen values gebonden worden aan object values. JSF voorziet ook in een State Saving mechanisme waardoor de status van pagina’s wordt onthouden door de server. Dit is handig als je moet terugkeren naar een eerdere pagina. JSF voorziet in een aantal componenten zoals inputTextBoxen, booleanSelectBoxen, outputTextBoxen, … Al deze componenten moeten tussen de <h:form></h:form> tags staan. Ze zijn te herkennen aan de tags die steeds beginnen met “h:” of “f:” 4.3.3.1 Expression Language (EL) Als we willen programmeren in JSF dan is kennis over de EL wel handig. Dankzij EL kunnen we in de JSF pagina’s bepaalde attributen opvullen met values. Values staan steeds tussen #{} tags. In EL kunnen we ook wiskundige berekeningen uitvoeren of boolean statements maken. De vertaling tussen de Java operators en de EL operators vind je in onderstaande tabel. Java + / % * && || ! Eindwerk Bram Gadeyne EL + div mod * and || of or not 2007-2008 37 < <= > >= == != lt le gt ge eq ne 4.3.3.2 Bindings Bindings in JSF zijn dankzij het gebruik van EL heel gemakkelijk begrijpbaar en gebruikbaar. In JSF gebeurt de configuratie altijd in een faces-config.xml file. Hieronder zie je een sterk gereduceerd voorbeeld. Als we vroeger objecten wilden “bekend” maken voor JSF dan moesten we die een “managed-bean-name” geven. Met die beanname kon de bean dan worden aangesproken. Dit kunnen we doen voor gewone instanties van POJO’s maar ook voor instanties van EJB’s zoals Entity klassen. <?xml version="1.0" encoding="UTF-8"?> <faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"> <managed-bean> <managed-bean-name>managedBean</managed-bean-name> <managed-bean-class>Bean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> </faces-config> Een voorbeeld van onze Bean.class is dan public class Bean { public Bean() { } String tekst; public String getTekst() { return tekst; } public void setTekst(String tekst) { this.tekst = tekst; } } We zien dat in Bean.class een value gedefinieerd is. Dit zou bijvoorbeeld een Entity kolomwaarde kunnen zijn die we later willen versturen naar de database. We kunnen nu deze waarde koppelen via binding aan bijvoorbeeld een h:inputText. <h:inputText value="#{managedBean.tekst}"> Eindwerk Bram Gadeyne 2007-2008 38 Zoals u kunt zien gebruiken we de managedBeanName om de bean op te roepen. Als value gebruiken we niet een getter of setter maar de overeenkomstige value naam zoals hier tekst. Dit is mogelijk dankzij de Java conventies voor getters en setters. Bij het laden van de pagina zal de getter van de value worden opgeroepen. Wanneer men dan een submit doet van het form waarin de inputText zich bevindt dan zal respectievelijk de setter van die value worden opgeroepen. Op die manier kunnen we dan in de back-end van ons programma verder werken met deze value zonder dat we ons zorgen hoeven te maken over het transport van die value tussen de client en de server via bijvoorbeeld een POST parameter of iets dergelijks. 4.3.3.3 Navigatie Navigatie tussen pagina’s is natuurlijk noodzakelijk in webapplicaties. In JSF gebeurt het surfen niet door het aanroepen van URL’s. De locatie van een webpagina kan op die manier veranderen en men kan nog acties laten uitvoeren alvorens effectief te navigeren naar een andere pagina. De configuratie kunnen we instellen nadat een bepaald woord “outcome” werd opgeroepen op een bepaalde pagina of nadat een bepaalde method werd uitgevoerd. Een voor beeld: <?xml version="1.0" encoding="UTF-8"?> <faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"> <navigation-rule> <navigation-case> <from-outcome>home</from-outcome> <to-view-id>/home.xhtml</to-view-id> </navigation-case> </navigation-rule> </faces-config> Wanneer JSF nu ergens de outcome “home” opvangt zal hij navigeren naar de view-id (pagina) home.xhtml. Op zich zal hij niet forwarden naar de effectieve pagina maar zal de pagina door JSF worden gerenderd en geladen. Renderen van een pagina houdt in dat de pagina door de JSF servlet wordt gelezen en dat de tags van deze pagina zullen worden omgezet naar HTML tags. Een JSF pagina moet dus altijd gerenderd worden om omgezet te worden naar HTML. Na het renderen van de JSF pagina zal deze verzonden worden onder de vorm van HTML. We kunnen dan zien wat onze url geworden is http://.../../home.seam. Via een Button kunnen we een navigatie afdwingen. <h:commandButton value="Home" action="#{navigator.goHome()}" /> We zien hier dat de button een waarde “Home” zal krijgen. Bij de action voeren we hier een method goHome() uit. Deze method kan een void method zijn waardoor we na het uitvoeren ervan op dezelfde pagina zullen blijven. Als de method een String terugkeert wordt naar de Eindwerk Bram Gadeyne 2007-2008 39 overeenkomstige view-ID gesurft. Als we een lege String teruggeven dan zal ook opnieuw de huidige pagina geladen worden. We kunnen eveneens in het action gedeelte de gewenste String definiëren als het oproepen van een method niet nodig is. @Name("navigator") public class Navigator { public String goHome() { //doe iets return "home"; } } 4.3.3.4 Lijsten In JSF kunnen we niet alleen gewone waarden doorgeven aan de JSF pagina. We kunnen ook collections doorgeven. Op die collections zit geen controle op het type object dat zich in de collection bevindt. We kunnen wel in de back-end via generics ervoor zorgen dat we enkel objecten van een bepaald type in de collection willen. <h:dataTable value='#{bean.collection}' var='item'> <h:column> <f:facet name="header"> <h:outputText value="Naam"/> </f:facet> <h:outputText value="#{item.naam}"/> </h:column> </h:dataTable> Deze dataTable is een tabel met slechts 1 kolom ter illustratie. We krijgen ergens een collection met de naam Collection binnen. Elk item uit de collection stel ik voor door de naam “item” zoals aangegeven bij het attribuut var. Als we nu zeker weten dat item een value bevat “naam” dan kunnen we die weergeven met bijvoorbeeld een outputText. De werking is ook weer dezelfde waarbij we niet de getter of setter naam gebruiken maar de effectieve naam van de value. We zien nog dat er een f:facet gedefinieerd is. Dit is telkens de waarde die we bovenaan in de kolom header zullen zien verschijnen. In ons geval gebruiken we hier een outputText met als value “Naam”. 4.3.3.5 Templating in JSF Na het genereren van een Seam project viel het me op dat hiervoor een soort templating werd voorzien waardoor andere pagina’s eigenlijk in een template worden geopend. De definitie van het template zelf ziet er uit als een gewone html pagina. In de body van de html pagina vinden we echter de volgende codes terug. Het eerste voegt een menu toe en vult een parameter in die door dit menu kan worden opgehaald. Eindwerk Bram Gadeyne 2007-2008 40 <h:form> <ui:include src="menu.xhtml"> <ui:param name="projectName" value="ComMaS"/> </ui:include> </h:form> Het tweede definieert waar een bepaalde “ui” code met als naam body uit de oproepende pagina zal worden toegevoegd. <div class="body"> <ui:insert name="body"/> </div> In een oproepende pagina vinden we dan de volgende tag rond de uiteindelijke inhoud terug. <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:rich="http://richfaces.org/rich" template="/layout/template.xhtml"> <ui:define name="body"> <h:form> <!--enige vorm van jsf-inhoud --> </h:form> </ui:define> </ui:composition> Bemerk dat als attribuut van de ui:composition het veld template wordt meegegeven. Deze verwijst dan naar de locatie van waar de template zich bevindt. Het ui:define blok heeft als naam “body” zodat het op de juiste plaats kan worden ingevoegd in de template. 4.3.4 Seam De rode draad doorheen mijn stage was niet zozeer het analyseren maar het ontwikkelen met de nieuwe Java technologie Seam waar ondertussen de nieuwe standaard webbeans op gebaseerd is. Seam is een open - source project van “JBoss , a devision of Red Had”. Het is niet een framework die volledig nieuwe zaken wil ontwikkelen. De doestelling van de Seam programmeurs is om bestaande “Proven Technology” (technologie die zijn kunnen al vaak heeft bewezen) te gebruiken en te vergemakkelijken in een nieuw framework. Zo neemt het bijvoorbeeld de moeilijke weg doorheen configuratie van verschillende frameworks in XML weg en vervangt deze door het Eindwerk Bram Gadeyne 2007-2008 41 gebruik van annotaties. Seam voorziet ook in een aantal tools die veel gebruikte standaardcomponenten kunnen vervangen. Zo denk ik maar aan het authenticatiesysteem waarin Seam voorziet. De 2 belangrijkste frameworks waarop het Seam framework is gebaseerd zijn JSF en EJB 3.0. Seam wenst gebruik te maken van de standaarden en gebruikt daarom deze 2 frameworks voor respectievelijk de presentation en de business layer van een applicatie. Meer uitleg over EJB 3.0 en JSF zijn terug te vinden in de vorige hoofdstukken. Daarnaast wordt ook gebruik gemaakt van logging frameworks en Persistence met Hibernate die later in dit verslag nog verder zullen worden uitgelegd. Voor de uitwerking van de extra functionaliteiten voorziet Seam in objecten die gemakkelijk via injections (zoals bij EJB) kunnen worden gekoppeld. Op die manier kun je Seam objecten raadplegen via een Proxy en zal het uiteindelijke component de gevraagde functionaliteit uitvoeren. De configuratie van al deze componenten heeft Seam gecentraliseerd in de kleine XML file components.xml. Maar over al deze zaken vind je verder in dit stageverslag nog veel informatie. 4.3.4.1 Starten van een nieuw project Seam voorziet in een tool met de naam “seam-gen”. Het maakt een volledig nieuw project met eventueel zelfs al pagina’s waarmee je acties over de verschillende databanktabellen kan uitvoeren. Door het installeren van de JBoss Tools in de Eclipse IDE kun je gemakkelijk zo’n nieuw project laten genereren. 4.3.4.2 EJB 3.0 in Seam 4.3.4.2.1 Injecties De JNDI naam van een EJB werd vroeger in een ejb-config.xml bestand beschreven. Op die manier kon men dan injecties uitvoeren van beans in andere beans. Seam houdt niet zo van configuratie bestanden. Om de JNDI naam te specificeren in Seam moet je gebruik maken van de @Name(“JNDINaam”) annotatie. Om dan de bean te kunnen injecteren in een andere maken we gebruik van de @In annotatie. De @In annotatie voorziet in een parameter create die een boolean waarde true of false kan krijgen. Als deze op true staat dan wil dit zeggen dat er mogelijks van die bepaalde te injecteren Bean nog geen instantie bestaat. Als dit zo is dan zal door de create=true optie de Container een nieuwe instantie van de EJB creëren. Soms willen we echter een aangepaste bean terugplaatsen op een bepaalde scope. Dit kunnen we ook gemakkelijk doen door de @Out annotatie te definiëren bij een bepaalde variabele. Een voorbeeld: Eindwerk Bram Gadeyne 2007-2008 42 @Stateless @Name(“beanOne”) public class BeanOne implements IBeanOne { //deze method moet ook beschreven staan in de interface IBeanOne om ze toegankelijk te //maken in de geïnjecteerde Bean. public void doIets() { //voert iets uit } //enkele datamembers en methoden } @Stateless @Name(“beanTwo”) public class BeanTwo implements IBeanTwo { @In(create=true) IBeanOne beanOne; public void doeIetsAnders() { beanOne.doIets(); } //enkele methoden en datamembers. } Zoals we kunnen zien moeten we steeds de Interface gebruiken van de bean die we willen raadplegen omdat we via RMI een proxy (stub) krijgen met een referentie naar de bean en niet de implementatie van de bean zelf. De proxy implementeert wel dezelfde interface als de bean. 4.3.4.2.1.1 Contexts Een ander voordeel aan Seam is dat je POJO’s (Plain Ordinary Java Objects) of EJB’s kunt annoteren met de @Scope annotatie. We kunnen dan kiezen om ons object in 1 van de 7 contexts van Seam op te slaan. Seam zal steeds alle contexts overlopen om een proxy voor een JNDI naam te vinden. Hij zal daarbij beginnen bij de context die de kleinste levensduur heeft. We kunnen bij het opzoeken van een bean via injectie echter ook opgeven in welke context Seam zal moeten zoeken. • • Stateless context o Deze context heeft niet echt een functie. We kunnen echter elk object in deze context stoppen als we ze op een stateless manier willen behandelen. Session context o De Sessie context wordt vaak gebruikt bij webapplicaties. Het is eigenlijk een plaats waarin je objecten kunt bewaren die doorheen de gehele duur van een sessie beschikbaar zijn. Meestal is dit dan vanaf het moment dat een gebruiker zich aanmeldt totdat deze zich terug afmeldt. Eindwerk Bram Gadeyne 2007-2008 43 • • • • • Application context o In deze context kunnen objecten worden geplaatst die niet zullen verschillen tussen de verschillende gebruikers en dus gedurende de hele levensduur van de applicatie zullen bestaan. Als je hier een Statefull EJB in plaatst, werkt de application context eigenlijk ook als een singleton. DAO’s zijn bijvoorbeeld objecten die voor iedereen hetzelfde zullen zijn. De meeste componenten die voorzien zijn door Seam zijn ook in de application context opgeslagen. Event context o Deze is de kleinste context van allemaal. In deze context worden objecten geplaatst die slechts beschikbaar moeten zijn tussen het moment van een submit op een form tot dat het antwoord wordt gestuurd. Page context o Hierin kunnen objecten worden bewaard voor de lengte van een page request. Zolang een pagina dezelfde blijft zal bij een refresh informatie bijvoorbeeld niet opnieuw moeten worden opgehaald uit de databank. Het is een manier om misbruik van de sessie te voorkomen. Het is een manier om professioneler te werken zonder request scope zodat niet bij elke refresh de databank opnieuw moet worden geraadpleegd. Conversation context o Deze context is ontworpen om het probleem met sessies over verschillende tabbladen in een browservenster op te lossen. Het is zo dat wanneer we een nieuw tabblad in een nieuwe browser openen we nog steeds in dezelfde sessie zitten. De conversation context maakt dan een soort virtuele sessies die met elkaar kunnen communiceren. Hierdoor zal de applicatie perfect over tabbladen kunnen werken en zal het lijken alsof we een nieuwe sessie hebben gestart. Business Process context o Deze context is ontworpen om business processen in te laten werken. Deze processen kunnen heel lang duren en worden soms automatisch opgestart. 4.3.4.3 Bingings in Seam In Seam houdt men niet van dergelijke configuratie. De manier van oproepen en het schrijven van de bean blijft dezelfde. Maar de volledige configuratie in de faces-config.xml file valt weg. Het configureren van de beanName gebeurt dan met de Seam annotatie @Name(“value”). Een aangepast voorbeeldje voor onze Bean.class import org.jboss.seam.annotations.Name; Eindwerk Bram Gadeyne 2007-2008 44 @Name("managedBean") public class Bean { public Bean() { } String tekst; public String getTekst() { return tekst; } public void setTekst(String tekst) { this.tekst = tekst; } } Het oproepen in de JSF pagina blijft dan als volgt: <h:inputText value="#{managedBean.tekst}"> 4.3.5 Rich Web Applications (Web 2.0) Om tegemoet te komen aan het idee van Web 2.0 voorziet Seam standaard in een implementatie van Richfaces. Richfaces is een library die p JSF is gebaseerd en componenten voorziet die goed samenwerken met AJAX. Web 2.0 is een begrip die binnen de webwereld de laatste tijd veel gebruikt wordt. Helaas bestaat er geen echte definitie van Web 2.0 omdat Web 1.0 nooit is beschreven en omdat Web 2.0 een toekomstvisie is zoals men graag de websites naar een nieuw niveau zou willen laten zien evolueren. Dankzij frameworks als Richfaces die gebruik maken van Ajax om hun componenten af te beelden en laten samenwerken, krijg je al een mooi voorbeeld van hoe Web 2.0 eruit zou kunnen gaan zien. 4.3.5.1 Richfaces Natuurlijk is JSF een basistaal en standaard waarop vele andere frameworks of componenten gebaseerd zijn. Ze maken natuurlijk allemaal wel gebruik van JSF. JSF op zich bevat wel enkele dynamische componenten waarmee je bijvoorbeeld lijsten, knoppen, linkbuttons, labels, tekstboxen, chekboxen, … kunt maken. De layout van al deze zaken is dan de standaard layout omdat de HTML die gegenereerd wordt de gewone HTML tags bevat. Frameworks zoals Richfaces voorzien in mogelijkheden om aan templating te doen. Ze voorzien dan een aantal css bestanden waarmee je via drag en drop al een hele mooie webpagina verkrijgt die meestal in alle webbrowsers mooi worden afgebeeld. Daarnaast bieden frameworks zoals Richfaces tegenwoordig ook ondersteuning voor AJAX. Dankzij Ajax kunnen we eigenlijk applicaties ontwikkelen die er ongeveer uit gaan zien als een lokale niet webapplicatie, omdat het effect van de steeds ladende pagina’s wegblijft. Eindwerk Bram Gadeyne 2007-2008 45 4.3.5.1.1 Componenten Richfaces voorziet in enkele handige componenten die het ontwikkelen voor een webapplicatie nog leuker maken. 4.3.5.1.1.1 rich:calender Één van de meest in het oog springende componenten is het kalender component. Door deze lijn code op een webpagina te plaatsen verschijnt de mooie kalender. De value wordt gebonden aan een Date object. Het datePattern is een optionele parameter maar geeft je de mogelijkheid om de datum in de plaatselijke weergave weer te geven. <rich:calendar value="#{actie.deadline}" datePattern="yyyy-MM-dd HH:mm" /> 4.3.5.1.1.2 rich:panel Om pagina’s op te delen kunnen panelen worden gebruikt. Deze kunnen dan op een heel gemakkelijke wijze voorzien worden van een header. <rich:panel> <f:facet name="header"> <h:outputText value="aanpassen type" /> </f:facet> ... </rich:panel> Eindwerk Bram Gadeyne 2007-2008 46 4.3.5.1.1.3 rich:tabPanel Werken met tabbladeren in een webapplicatie was nog nooit zo gemakkelijk als met deze control. Het tabpanel heeft een verzameling met tabs die op zich weer code kunnen bevatten. Standaard worden de tabs geladen via Ajax. We zien in dit voorbeeld dat er een action is opgegeven. Bij het switchen naar een ander tabblad kunnen we dus ook een method in de back-end laten uitvoeren. De UI:include is een tag die niet afkomstig is vanuit Richfaces maar uit facelets van JSF. Met deze tag kun je probleemloos andere pagina’s in een andere pagina includen. Deze pagina’s zullen dan ook weer gerenderd worden. Op die manier kun je eigenlijk handige componentjes zelf schrijven die op die manier ook hergebruikbaar zijn doorheen de applicatie. Het gebruik ervan in tabbladeren zorgt ervoor dat je de tabbladen op zich in apparte files kunt beschrijven wat het overzicht over de tabbladen behoudt. <rich:tabPanel id="tabPabel1" switchType="ajax"> <rich:tab id="medewerkerTab" label="personen" action="#{medewerkerAction.clearMedewerker()}"> <ui:include src="/medewerker/lijst.xhtml" /> </rich:tab> </rich:tabPanel> 4.3.5.1.1.4 rich:dataTable Net zoals JSF heeft richfaces een eigen implementatie van de DataTable control. Niet alleen de layout van dit component maakt het zo interessant. De samenwerking met Ajax is fenomenaal vooral als het samen wordt gebruikt met het volgende component de dataScroller. Eindwerk Bram Gadeyne 2007-2008 47 <rich:dataTable id="actieTable" value="#{bean.collectie}" rows="10" var="item"> <f:facet name="header"> <rich:columnGroup> <rich:column> <h:outputText value="naam" /> </rich:column> ... </rich:columnGroup> </f:facet> <rich:column> <h:commandLink action="#{actieAction.detailSetup()}" value="#{item.titel}" /> </rich:column> </rich:dataTable> 4.3.5.1.1.5 rich:dataScroller Als we een tabel hebben waarvan we niet alle records willen laten zien dan kunnen we dankzij deze scroller gemakkelijk onze tabel dynamisch opvullen. In het vorige voorbeeld hadden we bijvoorbeeld het aantal rijen (rows) op 10 ingesteld. Het opvullen van de gegevens gebeurt dan ook via Ajax waardoor dit relatief snel verloopt. <rich:datascroller for="actieTable" /> 4.3.5.1.1.6 rich:inputSlider Een leuk component is de inputSlider waarmee men een waarde visueel kan voorstellen tussen 2 waarden. <rich:inputNumberSlider minValue="1" maxValue="5" value="#{bean.value}" /> Eindwerk Bram Gadeyne 2007-2008 48 4.3.5.1.1.7 rich:inputSpinner Geeft net als de inputSlider de mogelijkheid om waarden gemakkelijk te veranderen. Ikzelf vind dat deze control niet echt een meerwaarde biedt. Het aantal toetsaanslagen zal meestal kleiner zijn dan het aantal muisklikken. <rich:inputNumberSpinner value="#{bean.value}"> 4.3.5.1.1.8 rich:tree Een component die ik ook veel heb gebruikt is een RichTree. Een tree programmeren voor het web is moeilijk maar dankzij Richfaces nu dus gemakkelijker dan ooit. Al is het Tree component toch één van de moeilijkste componenten om te gebruiken binnen Richfaces. <rich:tree id="tree" switchType="ajax" showConnectingLines="false" value="#{competentieAction.treeNode}" var="item" nodeFace="#{item.type}" ajaxSubmitSelection="true"> <rich:treeNode type="type" icon="/img/openfolder.png" iconLeaf="/img/closefolder.png"> <h:outputText value="#{item.typenaam} " /> </rich:treeNode> <rich:treeNode type="competentie" icon="/img/multicomp.png" iconLeaf="/img/comp.png"> <h:outputText value="#{item.naam} " /> </rich:treeNode> </rich:tree> Eindwerk Bram Gadeyne 2007-2008 49 De value die aan deze Tree gekoppeld wordt is van het type “org.richfaces.model.TreeNode”. Dit is echter alleen maar een abstracte klasse. Het uiteindelijke object dat we gebruiken om de Nodes voor te stellen zijn er van het type “org.richfaces.model.TreeNodeImpl”. Het belangrijkste wat we aan een dergelijke TreeNode kunnen meegeven is data in de vorm van gelijk wel Object. Ook kunnen we aan elke Node een collectie van ChildNodes toevoegen waardoor we de boomstructuur verkrijgen. Nu kunnen we opgeven welke nodes op welke manier in de tree moeten worden weergegeven. Dit doen we door bijvoorbeeld een @Transient veld type op te vullen. (meer informatie over @ Transient vind je bij het hoofdstuk over Persistence). In het bovenstaande voorbeeld wordt dit dan opgegeven als nodeFace. De juiste TreeNode wordt dan gekozen aan de hand van dit type. Per TreeNode kunnen we dan bepaalde looks veranderen zoals de icoontjes die moeten verschijnen voor een node. 4.3.5.1.1.9 Handige attributen Bij elke richfacescomponent kun je nog enkele attributen opgeven die soms wel handig kunnen zijn. Meestal zijn het attributen die een beperking voor de ingave verzorgen of die de layout van het component laten veranderen. Er zijn echter ook enkele attributen die bijna elk richfaces- of JSF-component voorziet. • • • Disabled: met dit attribuut kun je een boolean waarde opgeven die ervoor zorgt dan een component wel zichtbaar is maar niet wijzigbaar. Render: met dit attribuut kun je een boolean waarde meegeven die aanduidt of het component en zijn subcomponenten moeten worden weergegeven. Dit kan handig zijn om delen van het programma bijvoorbeeld af te schermen voor gebruiker die niet voldoende rechten hebben. ID: Elke component kunnen we een ID geven. Dit kan handig zijn bij het gebruik van Ajax. Eindwerk Bram Gadeyne 2007-2008 50 4.3.5.1.2 Problemen met de Tree Het gebruik van de Tree was in mijn project redelijk cruciaal. Het opvullen van de Tree en het afbeelden op zich vormden geen enkel probleem en werkten mooi samen met AJAX. Interactie op een Tree om bijvoorbeeld Nodes toe te voegen was iets wat moeilijk was. Het was een moeilijke opgave om te weten te komen welke Node nu precies geselecteerd was. Ik heb hiervoor 2 methodes uitgezocht waarvan ik uiteindelijk de laatste heb gebruikt. 4.3.5.1.2.1 De NodeSelectListener Bij de Tree kun je een attribuut opgeven die verwijst naar een methode en die werkt onder de vorm van een listener. nodeSelectListener="#{competentieAction.treeListener}" In mijn geval was dit dus de methode treeListener in mijn competentieAction Bean. De methode zag er ongeveer als volgt uit. public void treeListener(NodeSelectedEvent event) { UITree tree = (UITree) event.getComponent(); Object fromEvent = tree.getRowData(); try { if (fromEvent.getClass().equals(Type.class)) { Type type = (Type) fromEvent; // doe iets } if (fromEvent.getClass().equals(Competentie.class)) { Competentie competentie = (Competentie) fromEvent; //doe iets } } catch (RuntimeException e) { } } Zoals je kunt zien kun je bij elke NodeSelectedEvent die zich voordoet te weten komen welke Node nu precies geselecteerd was en welke Data hij bevatte. Helaas werkte deze listener niet perfect. Het gebeurde heel vaak dat een bepaalde Node uit de Tree 2 maal moest geselecteerd worden alvorens hij echt geselecteerd bleek te zijn. Hoewel bij het debuggen en dergelijke alles zeer normaal leek te verlopen aan de kant van de server, bleek dat de opnieuw gerenderde delen aan de client kant niet overeenstemden met de keuze. Ik merkte dat dit probleem zich vaker voordeed wanneer de server zwaar belast werd. Een echte oorzaak voor het probleem heb ik echter niet gevonden. Daarom ging ik op zoek naar een alternatief. 4.3.5.1.2.2 Checked Tree oplossing Wat mij ook was opgevallen bij mijn eerste oplossing was dat ik nooit visueel kon zien of de server nu begrepen had dat ik een bepaalde node had geselecteerd. Daarom plaatste ik een checkbox in mijn TreeNode. <h:selectBooleanCheckbox value=”select me"> Eindwerk Bram Gadeyne 2007-2008 51 <a4j:support event="onclick" actionListener="#{bean.listener}" /> </h:selectBooleanCheckbox> Aan een selectbox kan een Listener worden gehangen. Meer uitleg hierover vind je in het hoofdstuk over A4J (Ajax for JSF). public void listener(ActionEvent event) { Object o = findSelected(treeNode.getChildren()); setFalseVars(); if (o != null) { if (o.getClass().equals(Type.class)) { type = (Type) o; fromEvent=o; competentie = new Competentie(); nodeSelected = true; eType=true; type.setSelected(false); } if (o.getClass().equals(Competentie.class)) { competentie = (Competentie) o; fromEvent=o; type = new Type(); nodeSelected = true; eComp=true; competentie.setSelected(false); } } } @SuppressWarnings("unchecked") private Object findSelected(Iterator it) { Object foundObject = null; while (it.hasNext() && foundObject == null) { Entry e = (Entry) it.next(); TreeNode node = (TreeNode) e.getValue(); Object o = node.getData(); if (o.getClass().equals(Type.class)) { Type t = (Type) o; if (t.isSelected()) { foundObject = t; } } if (o.getClass().equals(Competentie.class)) { Competentie c = (Competentie) o; if (c.isSelected()) { foundObject = c; } } if (foundObject == null) { foundObject = findSelected(node.getChildren()); } } return foundObject; } De value van de chekbox was gebonden aan een @Transient boolean veld “selected”. Wanneer men dus ergens in de tree een selectbox aanvinkte dan werd deze selected value voor het Object op true gezet en werd de checkBoxListener uitgevoerd. Eindwerk Bram Gadeyne 2007-2008 52 Wanneer de Listener werd uitgevoerd werd eerst het geselecteerde object gezocht en indien die bestond teruggegeven. Met dat geselecteerde object konden we dan het gewenste uitvoeren. Deze manier bleek beter te werken. Je moest geen 2 maal het gewenste item selecteren en de gebruiker ziet ook visueel welke node hij/zij geselecteerd heeft. Dit visuele aspect is wel browserafhankelijk. Sommige browsers zullen een geselecteerd item geselecteerd laten terwijl anderen het zullen deselecteren. 4.3.5.1.3 Javascript in Richfaces Om een boodschap te verkrijgen die verschijnt met de vraag of ik zeker het gevraagde object wil verwijderen heb ik een eenvoudig javascript scriptje op het internet gevonden en bewerkt. <script language="JavaScript"> <!-// source: http://www.shiningstar.net/articles/articles/javascript/confirmsubmit.asp function confirmSubmit() { var agree=confirm("Verwijderen?"); if (agree) return true ; else return false ; } // --> </script> Ik wou dit script laten uitvoeren in een A4J commandLink. Daarin kun je een onclick event definiëren. Eerst had ik gewoon confirmSubmit() opgeroepen maar toen bleek zowel bij een true of false antwoord dat het verdere script niet werd uitgevoerd. Via de tool fireBug van Firefox kon ik gemakkelijk de gegenereerde javascriptcode bekijken. Richfaces voegt zelf ook nog code toe aan het onclick event. Omdat dit scriptje iets returnde, werd in ieder geval de rest van deze Richfaces javascript code niet meer uitgevoerd. Uiteindelijk heb ik dit probleempje dan kunnen oplossen door de confirmSubmit() methode als volgt op te roepen. onclick="if(!confirmSubmit()) return false" 4.3.5.2 Ajax For JSF (A4J) De ondersteuning voor Ajax in Richfaces zit intern ingebouwd maar maakt gebruik van A4J. Componenten op zich kunnen samenwerken met elkaar en gebruiken daarbij soms Ajax. Het TabPanel is daar 1 van de mooiste voorbeelden voor. Als programmeur heb je natuurlijk zelf ook graag de touwtjes in handen. Daarom kun je A4J gebruiken. Het voorziet in een aantal componenten die het mogelijk maken om Ajax support toe te voegen aan de gewone JSF componenten. Het voorziet ook in een paar componenten zoals buttons of links. Eindwerk Bram Gadeyne 2007-2008 53 4.3.5.2.1 Controls 4.3.5.2.1.1 A4J:CommandButton De A4J commandButton heeft een attribuut reRender. Bij dit attribuut kun je de id van een component opgeven die gererendered moet worden. De button kan uiteraard ook een actie uitvoeren. <a4j:commandButton action="#{bean.someAction()}" value="dit is een knop" reRender="idVanRichComponent"> </a4j:commandButton> 4.3.5.2.1.2 A4J:CommanLink De commandLink heeft dezelfde functionaliteiten als de commandButton. Ze wordt alleen weergegevens als een link in plaats van een knop. <a4j:commandLink action="#{bean.someAction()}" value="dit is een knop" reRender="idVanRichComponent"> </a4j:commandLink> 4.3.5.2.1.3 A4J:support <h:selectBooleanCheckbox value=”select me"> <a4j:support event="onclick" actionListener="#{bean.listener}" /> </h:selectBooleanCheckbox> De A4J:support voegt mogelijkheden toe aan een JSF component om toch via AJAX te kunnen werken. Het belangrijkste attribuut dat we moeten opgeven is het event attribuut waarin we elk event type uit de gewone html kunnen opgeven. In dit voorbeeld voegen we een actionListener toe aan de checkbox. 4.3.5.2.1.4 A4J:status Dit component voorziet in een mogelijkheid om visueel weer te geven wanneer een Ajax request bezig is. Hieronder zien we een voorbeeldje. Tijdens de request wordt de tekst “loading…” weergegeven op de gewenste locatie. <a4j:status startText="loading..."></a4j:status> 4.3.6 Seam Logging Één van de eerste componenten die ik gebruikt heb en waarin Seam voorziet is een logging mechanisme gebaseerd op het framework Log4J. Het loggen van gebeurtenissen die zich voordoen binnen een applicatie wordt door sommige programmeurs gedaan door een volledige stacktrace in de serverlog op te slaan. Mensen die zich bezighouden met het deployen van een applicatie hebben hier echter niet veel aan. Voor hen is het gemakkelijker om bijvoorbeeld een foutcode door te geven aan een programmeur die dan de fout kan reproduceren of traceren. Eindwerk Bram Gadeyne 2007-2008 54 Ook het gebruik van System.out.println(“”); statements is hierbij niet echt een goede zaak. Soms kan het handiger zijn dat logging code weggeschreven wordt naar een database of naar een andere vorm van dataopslag. Frameworks bieden een oplossing voor deze problemen. Seam heeft een eigen implementatie van Log4J van apache geïmplementeerd. Op die manier kun je gemakkelijk kiezen of een loggingstatement moet output geven naar een io.writer, een a4j server of vele andere outputmanieren. De gelogde messages kun je opdelen in een aantal niveaus TRACE, DEBUG, INFO, WARN, ERROR en FATAL. Aan de hand van deze niveaus kan de programmeur sneller weten om welk door messages het gaat en eventueel de ernst van de fout bepalen. Seam voorziet in een Log object die gemakkelijk via injectie kan geraadpleegd worden. Door de volgende code in een EJB te plaatsen kunnen we deze loggen. Het zal ook steeds bij een logstatement weergeven uit welk object het gelogde statement komt. @Logger Log log; Het loggen zelf gebeurt dan automatisch. Het enige wat we zelf nog moeten voorzien zijn log statements. Voor een infobericht kan dit het volgende zijn. log.info("createSetup uitgevoerd."); Een error bericht die we meestal in een catch blok zetten kan dit zijn. try{ //iets } catch (Exception e) { log.error("kon createSetup niet uitvoeren." + e.getMessage()); } De configuratie van de logging kan voor de jboss server gebeuren via het configuratie bestand jboss-log4j.xml. Seam zal de implementatie van de Log4J van de JBoss server gebruiken. Enkele problemen die ik echter tegenkwam bij het gebruik van de JBoss logging kun je terugvinden bij het hoofdstuk over JBoss AS 4. 4.3.7 Seam Mail Seam voorziet in een mail component die je toelaat om gemakkelijk mails op te stellen in samenwerking met JSF. Hiervoor gebruikt Seam een implementatie van JavaMail Mail wordt gegenereerd via een Renderer object. Zoals alle andere objecten in Seam kun je de Renderer via injection opvragen. @In(create = true) private Renderer renderer; Hieronder een codevoorbeeld voor het versturen van mails. Hier wensen we bijvoorbeeld een object actie met als EL-naam actieconv te gebruiken in onze mail. Daarna laten we de renderer de Eindwerk Bram Gadeyne 2007-2008 55 mail renderen en plaatsen een informatiebericht in onze log. De Seam Mail syntax ziet er als volgt uit: Contexts.getConversationContext().set("actieconv", actie); renderer.render("/mail/actiemail.xhtml"); log.info("reminder sent for actie"); Hierna vind je een voorbeeld van de mail die we graag zouden versturen. We merken de “m:” tags die afkomstig zijn uit Seam Mail. Ze laten ons toe om standaard onderdelen van een mail zoals de verzender, ontvanger, onderwerp, body, attachments, … te configureren en in te vullen. <m:message xmlns="http://www.w3.org/1999/xhtml" xmlns:m="http://jboss.com/products/seam/mail" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <m:from name="ComMaS" address="[email protected]" /> <m:to name="#{actieconv.medewerkerid.voornaam} #{actieconv.medewerkerid.naam}" address="#{actieconv.medewerkerid.mail}"></m:to> <m:subject>Reminder for action</m:subject> <m:body> <!--de ingevulde body met gebruik van het actie object actieconv --> <p>Title:</p> <p> #{actieconv.titel}</p> </m:body> </m:message> Het opstellen en verzenden van een mail in Seam is dus zeer eenvoudig geïmplementeerd. 4.3.8 Seam Timer Seam voorziet in een mogelijkheid om methoden te definiëren die asynchroon kunnen worden uitgevoerd. Dit wil zeggen dat ze bijvoorbeeld eenmalig op een bepaald tijdstip of meerdere malen dankzij een bepaalde frequentie zullen worden uitgevoerd. Hiervoor gebruikt Seam een implementatie van het framework Quartz die dezelfde functionaliteit wil aanbieden. Een voorbeeld van een Asynchrone methode is @Asynchronous public Timer processIets(@IntervalDuration Long interval, @Expiration Date when) { System.out.println(“iets gedaan”); return null; } Als we deze methode in een interface definiëren moeten we ook daar deze annotaties voorzien. Het starten van een Asynchrone methode kan gewoon gebeuren door deze op te roepen en de overeenkomstige values in te vullen. De @IntervalDuration annotatie geeft de frequentie in milliseconden aan tussen het uitvoeren van de methode. De @Expiration annotatie bevat een datum waarop de assynchrone uitvoering van deze method zal worden gestopt. Eindwerk Bram Gadeyne 2007-2008 56 4.3.9 Seam Timer met Seam Mail Op een gegeven moment kwam er de vraag om via Seam automatische mail generatie te voorzien. Omdat zowel het mailen binnen Seam perfect werkte alsook het uitvoeren van een Asynchrone methode leek de combinatie van de 2 een heel eenvoudige oplossing. Helaas ben ik na lang zoeken tot de vaststelling moeten komen dat de werking van die 2 functies binnen Seam samen niet ondersteund is. De Seam Mail maakt gebruik van een component Renderer die ergens in de ApplicationContext opgeslagen is. Helaas kan men vanuit een Seam Timer die in een andere Thread wordt uitgevoerd deze Context niet opvragen waardoor het uitvoeren van de render methode onmogelijk is en dus ook het automatisch versturen van Mails. Binnen JBoss is dit probleem gekend en staat hetzelfde probleem vermeld op de volgende 2 aan elkaar gelinkte Jira websites. Jira is een framework die voorziet in bug management voor projecten. Op die manier kunnen bugs binnen een bepaald project gemakkelijk worden gevolgd en opgelost. JBoss belooft een oplossing voor dit probleem in de volgende release van Seam namelijk Seam 2.1.0 GA. http://jira.jboss.com/jira/browse/JBSEAM-2915 http://jira.jboss.com/jira/browse/JBSEAM-2507 4.3.10 Seam authenticatie Authenticatie is tegenwoordig zeer belangrijk geworden bij het gebruik van webapplicaties. Een gebruiker is meestal voorzien van een gebruikersnaam en een paswoord om taken op de webapplicatie uit te voeren. Ook hier heeft Seam een oplossing voor. Het zogeheten Identity object laat toe om een gebruiker voor de duur van een sessie in te laten loggen. Via die Identity zal Seam de rollen waarvan de gebruiker lid is kunnen terugvinden en zo de applicatie beveiligen. 4.3.10.1 Het Gebruik @In() Identity identity; identity.addRole(“een rol”); In JSF kunnen we dan gemakkelijk controleren of de huidige gebruiker een bepaalde rol heeft door het rendered attribuut van het JSF component op te vullen met de s:hasRole(“rol”) functie. rendered="#{s:hasRole('c') or s:hasRole('pv') or s:hasRole('a')}" We kunnen ook pagina’s afschermen op basis van de rollen van een gebruiker. Dit kunnen we doen in de pages.xml file. <page view-id="/admin.xhtml" login-required="true"> <restrict>#{s:hasRole('c') or s:hasRole('ps') or s:hasRole('pv') or s:hasRole('a')}</restrict> </page> Eindwerk Bram Gadeyne 2007-2008 57 We moeten zorgen dat layout items nooit login required zijn. De kans bestaat anders dat onze applicatie raar reageert wanneer een pagina moet worden weergegeven. De helft van de layout zou kunnen verdwenen lijken. Daarom heb ik ook nog de volgende regels in mijn pages.xml toegevoegd. <!-- layout items mogen niet login-required zijn --> <page view-id="/layout/*" login-required="false" /> <page view-id="/img/*" login-required="false" /> <page view-id="/stylesheet/*" login-required="false" /> Een method kunnen we ook voorzien van een @Restrict annotatie waarin we dan net zoals in JSF de EL-expressie s:hasRole(“”) kunnen gebruiken. @Restrict("#{s:hasRole('c') or s:hasRole('pv') or s:hasRole('a')}") public String uploadKlantentevredenheid() { fileUploaderService.uploadKlantentevredenheid(data, fileName); return "medewerker_detail"; } 4.3.10.2 De Configuratie In de components.xml file moeten we de security:identity tag opvullen om aan te geven welke method we willen gebruiken om de login te verifiëren. <security:identity authenticate-method="#{loginService.login}" remember-me="true" /> 4.3.11 Seam Fileupload/filedownload FileUpload is in Seam heel gemakkelijk geïntegreerd. Over het effectieve transport van gegevens tussen client en server hoef je je als programmeur eigenlijk geen zorgen meer te maken. Hiervoor maakt Seam gebruik van de library’s uit het commons fileupload project. Commons is een project van Apache die graag functionaliteiten wil groepen voor veel gebruikte (common in het engels) functionaliteiten. In de JSF pagina kunnen we gebruik maken van het Seam component s:fileUpload. <s:fileUpload id="artwork" data="#{fileUploader.data}" fileName="#{fileUploader.fileName}" size="40" maxlength="40" required="true" > </s:fileUpload> De belangrijkste zaken die we hier gebruiken zijn de data en filename binding. In onze bean voorzien we dan ook een getter en setter voor deze 2 zaken. We kunnen dan via een button een action laten uitvoeren zoals uploadKlantentevredenheid(). De data-array moeten we in de constructor instantiëren op een bepaalde lengte. De data-array zal dan in de service weggeschreven worden naar een file met de bepaalde fileName. @Stateless @Name("fileUploader") @Scope(ScopeType.APPLICATION) Eindwerk Bram Gadeyne 2007-2008 58 public class FileUploaderAction implements IFileUploader { public FileUploaderAction() { data = new byte[10000]; } @In(create = true) @Out IFileUploaderService fileUploaderService; private byte[] data; private String fileName; public String uploadKlantentevredenheid() { fileUploaderService.uploadKlantentevredenheid(data, fileName); return "medewerker_detail"; } public byte[] getData() { return data; } public void setData(byte[] data) { this.data = data; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } } Om een bestand opnieuw te downloaden voorziet Seam, voor zover ik heb kunnen achterhalen, echter niet echt een oplossing. Ik heb na lang zoeken toch een oplossing gevonden die via de gewone JSF kan worden gebruikt. Om een bestand te downloaden voorzien we ergens op een webpagina een knop die een actie kan uitvoeren. Deze knop mag geen A4J button zijn want om een bestand door te zenden willen we geen AJAX verwerking gebruiken. Hieronder zien we een voorbeeld om het downloaden van bestanden tussen een client en een server mogelijk te maken. JSF is gebaseerd op JSP. JSP is dan weer gebaseerd op servlets. In dit voorbeeld moeten we teruggaan naar de basisarchitectuur van java webapplicatie. Een servlet bevat steeds een HttpServletRequest en een HttpServletResponse die overeen komen met de request en response van een http event. Via de response heeft een servlet toegang tot een outputstream die gebruikt wordt om de http-content zoals webpagina’s naar de client te kunnen verzenden. In JSF gaan alle webpagina’s door 1 zo’n servlet genaamd de “faces servlet”. Die heeft natuurlijk ook toegang tot zo’n OutputStream. In dit voorbeeld hieronder zal de method writeToOutPutStream() de OutputStream van de “faces servlet” opvragen. Hij zal ook een InputStream maken die het mogelijk maakt om een File uit het systeem te lezen. Eindwerk Bram Gadeyne 2007-2008 59 Als laatste zal de streamCopy() methode de bytes uit de InputStream kopiëren naar de OutputStream. Als dit gebeurt is dan wordt de OutputStream geflusht (leeggemaakt) en gesloten. Er wordt een responseComplete() vlag opgeroepen zodat JSF weet dat hij nu de gehele inhoud van de OutputStream mag doorsturen naar de client. Hier onder het uitgewerkte voorbeeld voor een download method in Seam. @Name("fileUploaderService") @Stateless @Scope(ScopeType.SESSION) public class FileUploaderService implements IFileUploaderService { @Logger Log log; //meer info over de logger in het hoofdstuk over Seam logging public void downloadKlantentevredenheid(Klantentevredenheid kt) { String fileDest = “…” // een bestandslocatie writeToOutputStream(fileDest, kt.getBestand()); } public void writeToOutputStream(String fileDest, String fileName) { try { File file = new File(fileDest); FileInputStream iStream = new FileInputStream(file); ExternalContext ectx = FacesContext.getCurrentInstance() .getExternalContext(); HttpServletResponse response = (HttpServletResponse) ectx .getResponse(); try { OutputStream out = response.getOutputStream(); response.setHeader("Content-disposition", "attachment; filename=" + fileName); streamCopy(iStream, out); out.flush(); out.close(); FacesContext.getCurrentInstance().responseComplete(); file.delete(); } catch (IOException ex) { file.delete(); } } catch (FileNotFoundException e) { log .error("kon geen writeToOutputStream uitvoeren" + e.getMessage()); } } public void streamCopy(FileInputStream fileInputStream, OutputStream outputStream) throws IOException { I f (fileInputStream == null || outputStream == null) return; byte abyte0[] = new byte[8192]; int i; synchronized (fileInputStream) { synchronized (outputStream) { while ((i = fileInputStream.read(abyte0)) != -1) outputStream.write(abyte0, 0, i); Eindwerk Bram Gadeyne 2007-2008 60 } } } } 4.3.12 Seam Taalondersteuning Een applicatie niet kunnen vertalen is ondenkbaar geworden bij het maken van grote projecten. In Java gebruikt men hiervoor messages.properties bestanden. Properties-bestanden zijn bestanden die sleutels (keys) bevatten aan de hand van welke we een waarde (value) kunnen opvragen. Het bestand Messages.properties bevat hiervoor dan de defaultwaarden. Messages_nl.properties bevat dan de waarden voor een Nederlandstalige pagina. Seam zal de juiste taal kiezen aan de hand van de ingestelde locale van de browser van de client. We kunnen deze natuurlijk zelf verzetten dankzij het gebruik van de EL en door het localeSelector component van Seam. Een voorbeeld met een selectbox in Seam. <h:selectOneMenu value="#{localeSelector.language}"> <f:selectItem itemLabel="English" itemValue="en"/> <f:selectItem itemLabel="Deutsch" itemValue="de"/> <f:selectItem itemLabel="Francais" itemValue="fr"/> </h:selectOneMenu> <h:commandButton action="#{localeSelector.select}" value="Change"/> Hier zal een gebruiker een taal kunnen kiezen en dit bevestigen door op een knop “Change” te klikken. Ik heb echter zelf een andere implementatie gebruikt door middel van linkButtons omdat er dan slechts 1 druk op de knop nodig is om de gewenste taal te kiezen. <h:commandLink value="NL" action="#{localeSelector.selectLanguage('nl')}" /> Er bestaan ook mogelijkheden om dynamisch alle beschikbare locales op te vragen via de localeSelector om daarmee dan een selectOneMenu dynamisch op te kunnen vullen. In een component zelf kunnen we de key van een bijhorende value gemakkelijk linken door de key op te vullen met de code zoals “commas.hello” in het volgende voorbeeld. Aan de hand van deze key zal de value worden opgevuld met de waarde van de bijhorende locale. De key in onderstaand voorbeeld is “commas.hello”. <h:outputText value="#{messages['commas.hello']}" /> 4.3.13 Persistence – Hibernate Persistence is niet meer weg te denken bij de creatie van nieuwe webapplicaties. Het is een hele handige tool om datamodellen om te zetten in objecten of omgekeerd. Zo’n omgezet object wordt dan een entity genoemt. Eindwerk Bram Gadeyne 2007-2008 61 Een entity bevat voor elke kolom in een bepaalde tabel een waarde met de bijhorende getter en setter. Een tabel heeft meestal ook een aantal referenties naar andere tabellen. Deze andere tabellen kunnen ook omschreven worden als een entity klasse. Om de referenties weer te geven wordt er dan gebruik gemaakt van collecties die entity klassen bevatten. Voor een many to one relatie wordt een instantie van het gerelateerde entity object bijgehouden. Een entity klasse heeft ook steeds een id. Deze id kan een veld zijn die geannoteerd is met de @Id annotatie zoals in onderstaand voorbeeld. Een id kan ook samengesteld zijn uit een aantal velden. In zo’n geval moeten we een samengestelde id definiëren. In zo’n geval wordt een nieuwe klasse opgesteld met daarin deze velden en hun getters en setter. Deze klasse wordt dan @Embeddable gedefinieerd. In de entity wordt dan een instantie van deze embeddable klasse bijgehouden en geannoteerd met @EmbeddedId. Boven een Collectie kan men een CascadeType opgeven. Dit geeft aan wat er moet gebeuren met de gerelateerde rijen in andere tabellen wanneer deze entity zou worden verwijderd. Een voorbeeld van een medewerker entity object: Eindwerk Bram Gadeyne 2007-2008 62 @Entity public class Medewerker implements Serializable { @Id @GeneratedValue(generator = "MedewerkerSeq") @SequenceGenerator(name = "MedewerkerSeq", sequenceName = "MEDEWERKER_SEQ", allocationSize = 1) private Long id; private String persnr; private String mail; private String naam; private String verkortenaam; private String voornaam; private String username; private Long password; private String rol; @ManyToOne @JoinColumn(name = "CHEF") private Medewerker chef; @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "medewerkerid") private Set<GevolgdeOpleiding> gevolgdeOpleidingCollection; @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "medewerkerid") private List<Competentiefiche> competentieficheCollection; @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "medewerkerid") private Set<PersoonlijkeOpleiding> persoonlijkeOpleidingCollection; @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "medewerkerid") private Set<PoVerslag> poVerslagCollection; @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "medewerkerid") private Set<Actie> actieCollection; @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "medewerkerid") private Set<Klantentevredenheid> klantentevredenheidCollection; //getters en setters } Seam gebruikt voor zijn persistence laag hibernate. Hibernate is een framework die voorziet in persistence mogelijkheden Omdat Seam streeft naar het gebruik van standaarden wordt echter persistence gebruikt via JPA. JPA is een standaard van Sun waaronder een bestaand persistence framework kan gekoppeld worden Het gebruik van hibernate zelf merk je dus niet echt. Een ander voorbeeld van een persistence framework is bijvoorbeeld Toplink van Oracle. Als programmeur moet je het configuratiebestand persistence.xml invullen (of Seam doet dit voor jou wanneer je een nieuw project start). Een voorbeeld van zo’n xml bestand vind je hieronder. Zoals je kan zien zal een persistence-unit aangemaakt worden met een bepaalde naam. Hiervoor zal een bepaalde provider gebruikt worden. In ons geval is dit dan hibernate. <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence Eindwerk Bram Gadeyne 2007-2008 63 http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="ProjectCommasPU"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>java:/jdbc/OracleDS</jta-data-source> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.show_sql" value="false"/> <property name="hibernate.format_sql" value="true"/> <property name="jboss.entity.manager.factory.jndi.name" value="java:/ProjectCommasEntityManagerFactory"/> </properties> </persistence-unit> </persistence> Door persistence te configureren kunnen we gebruik maken van een entity manager. Zo’n manager weet hoe hij connectie kan maken met de datasource en kent een aantal acties om rijen uit de database om te zetten naar entity objecten en voorziet in CRUD(create, read, update, delete) mogelijkheden voor deze objecten in de databank. Het oproepen van de entity manager is dankzij JPA heel gemakkelijk. Dankzij de annotatie @PersistenceContext wordt voor ons een entity manager geïnjecteerd op de geannoteerde locatie. Een voorbeeld: @PersistenceContext(unitName = "ProjectCommasPU") private EntityManager entityManager; Seam voorziet echter ook zelf in een implementatie van zo’n entity manager waardoor we zelfs de unitName van de gewenste entity manager niet moeten kennen. Dit is de manier om een entity manager op te vragen in Seam. @In(create=true) private EntityManager entityManager; In mijn project heb ik af en toe ook gebruik gemaakt van de @Transient annotatie die het mogelijk maakt om een extra veld toe te voegen aan een entity zonder dat deze effectief beschikbaar is in de database. Persistence zal dit veld dan ook negeren bij het wegschrijven van waarden naar een nieuwe of een geüpdate rij. 4.3.14 Rapportering Voor het maken van rapporten heb ik gebruik gemaakt van Jasperreports van JasperSoft. Een IDE die het mogelijk maakt om Jasperreports te genereren is IReport die ook van JasperSoft is. Ze worden beiden hieronder wat meer toegelicht. 4.3.14.1 IReport Om de rapporten te kunnen ontwerpen heb ik gebruik gemaakt van IReport van Jaspersoft. Deze handige tool maakt het gemakkelijk om via wizards de jrxml files te genereren. Deze jrxml files bevatten de beschrijving van een rapport in XML. IReport kan via een plugin ook zorgen voor het compileren van deze jrxml files naar jasper files welke Jasperreports nodig heeft om het uiteindelijke rapport te kunnen genereren. Eindwerk Bram Gadeyne 2007-2008 64 In IReport kunnen we aan de hand van een wizard een datasource definiëren. Die laat ons dan toe om een query te schrijven. Uit de query zal IReport alle benodigde Fields halen en ze in een rapport verwerken. We kunnen dan detailweergaven maken die op basis van groepsbreking van een aantal velden werkt. We kunnen ook Subrapporten toevoegen die ons toelaten extra informatie via een bepaalde parameter en query aan het rapport toe te voegen. In IReport kunnen we de rapportgeneratie al testen door het gebruik van de actieve datasource connectie. Hieronder zien we een screenshot van een rapport in IReport. Bovenaan kunnen we allerlei componenten toevoegen als tekstvelden, grafieken, afbeeldingen en subrapporten. Het rapport is opgedeeld in een titelblad, een paginabegin, detailweergave die per record zal worden ingevuld en een pagina footer. 4.3.14.2 JasperReports JasperReports laat toe om rapporten te genereren vanuit een datasource. Die rapporten kun je dan bijvoorbeeld naar PDF, xml, webpagina’s, tekst en nog andere laten afdrukken. Jasperreports heeft hiervoor .jasper files nodig of .jrxml files waaruit je *.jasper files kun compileren. Eindwerk Bram Gadeyne 2007-2008 65 Om PDF’s te kunnen genereren maakt JasperReports gebruik van de IText library. IText is een gratis Java library die PDF’s kan genereren. Op zich is JasperReports dus een library die functionaliteit voorziet om rapporten te genereren in een aantal formaten en door het gebruik van een datasource. Ook grafieken laten genereren van allerlei gegevens is mogelijk met JasperReports. 4.3.15 Testing Testing is een onderdeel van de programmatie van een applicatie waar tegenwoordig veel belang aan wordt gehecht. Een goede test kan nadien uitwijzen of de applicatie na het aanbrengen van wijzigingen nog steeds goed zal werken. 4.3.15.1 JUnit 4 Standaard testen worden in het framework JUnit geschreven. In de nieuwe JUnit 4 worden testen geschreven door ze te annoteren met de @Test annotatie. We kunnen ook een @Before methode definiëren om voor elke test een aantal zaken uit te laten voeren. Via assert methoden kunnen we dan enkele uitkomsten vergelijken om te laten blijken of onze test gelukt is of niet. Een niet opgevangen Exception laat ook onze test falen. Een voorbeeld van een JUnit 4 test klasse: Eindwerk Bram Gadeyne 2007-2008 66 import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; public class LoginActionTest { ILoginAction loginAction; @Before public void setUp() throws Exception { loginAction=new LoginAction(); } @Test public void testLoginTrue() { //iets doen zodat een positieve login plaatsvindt assertEquals("medewerker_detail", loginAction.login()); } @Test public void testLoginFalse() { //iets doen zodat een negatieve login plaatsvindt loginService.setIncome(false); assertEquals("", loginAction.login()); } } 4.3.15.2 DBUnit Omdat JUnit standaard buiten een Application Server en dus gewoon in een IDE wordt uitgevoerd kunnen we standaard geen persistence testen of andere testen die gebruik maken van een bepaalde Container (zoals EJB) uitvoeren. Voor het gebruik van Persistence is immers een connectie met een databank en een PersistenceContext nodig. DBUnit voorziet een uitbreiding op JUnit die wel toelaat om een PersistenceContext te gebruiken. In onderstaand voorbeeld kunnen we de werking van DBUnit volgen. Deze klasse test onze ActieDAO. • • • • Onze testklasse extends van BaseSessionBeanFixture<ActieDAO>. BaseSessionBeanFixture is een abstracte klasse die via Generics onze ActieDAO beschikbaar zal maken als een SessionBean met toegang tot een PersistenceContext. In de klasse definiëren we een class[] waar we al onze entity klassen in opsommen. In de constructor roepen we de super constructor op met als argumenten de ActieDAO klasse en de array van entity klassen. In een methode kunnen we dan onze te testen ActieDAO opvragen door de getBeanToTest() methode op te roepen. Eindwerk Bram Gadeyne 2007-2008 67 /** * The Class ActieDAOTest. */ public class ActieDAOTest extends BaseSessionBeanFixture<ActieDAO> { /** The Constant usedBeans. */ @SuppressWarnings("unchecked") private static final Class[] usedBeans = { Actie.class, Sessie.class, Medewerker.class, Opleiding.class, GevolgdeOpleiding.class, Competentiefiche.class, Klantentevredenheid.class, PersoonlijkeOpleiding.class, Competentie.class, Type.class, PoVerslag.class, Onderwerp.class, Todo.class, OpleidingCompetentie.class, CompetfFbeschrijving.class, Functiebeschrijving.class, Functieprofiel.class, PersoonlijkeCompetentie.class, VerwachteCompetentie.class, Task.class}; /** * Instantiates a new actie dao test. */ public ActieDAOTest() { super(ActieDAO.class, usedBeans); } /** * Test get by medewerker. */ public void testGetByMedewerker() { Medewerker medewerker=new Medewerker(); medewerker.setId(1L); final ActieDAO dao = getBeanToTest(); List<Actie> lijst=dao.getByMedewerker(medewerker); assertNotNull(lijst); } 4.3.15.3 MockObjecten Ik wou testen uitvoeren voor alle klassen. Het probleem bij een gelaagd model is echter dat de testen moeten uitwijzen of de klasse op zich de gewenste uitwerking heeft en niet of de onderliggende lagen hun werk goed doen. Wijzigingen in de ene laag mogen immers ook geen gevolgen hebben op de andere. Vandaar dat ik gebruik maakte van MockObjecten om testen uit te voeren. Een MockObject is een object dat gebaseerd is op de interface van een klasse van een onderliggende laag. Op zich returnen alle methoden van een MockObject een lege lijst of een nieuwe instantie van het te returnen object. Je kunt ook Objecten of lijsten laten teruggeven die op zich ook wel iets meer instantiatie hebben gekend als dat belangrijk zou zijn. Het belangrijkste is dat de uitkomst van een dergelijk MockObject steeds dezelfde is zodat de testen hierop gebaseerd kunnen worden. 4.3.15.4 Problemen met testing in Seam en EJB3 In Seam wordt vaak gebruik gemaakt van Injectie. Dit gebeurt echter niet op de standaard manier via de @EJB annotatie maar met de @In en @Out annotatie van Seam. Een JUnit test herkent deze Injecties echter niet waardoor zich tijdens het testen NullPointExceptions kunnen voordoen. Eindwerk Bram Gadeyne 2007-2008 68 Ook het gebruik van de @Logger annotatie bracht NullPointExceptions met zich mee waardoor overal in de code hiervoor een try catch blok moest worden voorzien. Seam heeft weliswaar een eigen integratie van het TestNG framework die een tegenhanger is voor JUnit 3. Helaas wordt deze testomgeving minder vaak gebruikt. Zeker omdat nu JUnit 4 de meeste problemen van JUnit 3 zou aangepakt hebben. 4.3.16 Exception handling Seam voorziet in een manier om aan exception handling te doen. Soms valt het voor dat er zich in Seam een fout voordoet die niet kan opgevangen worden. Ook in de code van de programmeur kan dit uiteraard voorvallen. Om dit probleem op te vangen kun je in de pages.xml file een stukje XML code toevoegen die zal uitgevoerd worden bij het voorvallen van bepaalde Exceptions. Een voorbeeld om ViewExpiredExceptions op te vangen is de volgende. <exception class="javax.faces.application.ViewExpiredException"> <redirect view-id="/login.xhtml"> <message>The session has expired</message> </redirect> </exception> Helaas is dit onderdeel van Seam nog lang niet in orde. Er zijn heel wat fouten binnen Seam die zelfs na het instellen op de pages.xml file niet zullen worden opgevangen. Op de volgende JIRA-site van JBoss kun je één van dergelijke fouten terugvinden. Een oplossing voor het probleem belooft men in de toekomst. http://jira.jboss.com/jira/browse/JBSEAM-2719. 4.3.17 Servers 4.3.17.1 Jboss AS 4 JBoss voorziet naast frameworks zoals Seam en Richfaces ook in zijn welbekende open-source Application Server. Deze server is veel lichter dan bijvoorbeeld een Glassfish server. Een nadeel is wel dat configuratie niet in een mooie IDE kan gebeuren maar via verschillende XML files moet gebeuren. Het voorziet ook in ondersteuning voor J2EE webapplicaties. Op zich is het gebaseerd op de andere open-source Java AS Apache Tomcat. Voor het gebruik van Seam is de JBoss AS heel handig omdat bij de AS ook alle benodigde libraries voor Seam alsook de Seam library zelf voorzien is. Seam zou natuurlijk ook op andere Application Servers moeten werken. Ik heb helaas bij het gebruik van JBoss AS 4 ook 2 grote problemen ondervonden. 4.3.17.1.1 Server Log Op een gegeven moment kreeg ik van Windows de opmerking dat mijn harde schijf nog maar 100 MB schrijfruimte vrij had. Enkele ogenblikken later was dit zelfs gereduceerd tot 0MB. Toen ik op zoek ging naar de oorzaak van het probleem bleek dat de Server log van de JBoss Server ongeveer Eindwerk Bram Gadeyne 2007-2008 69 3,5 GB groot was geworden. De oorzaak van dit probleem was terug te vinden in de configuratie van de Log4J implementatie waarin de JBoss Server ook standaard voorziet. Logging gebeurde standaard op debug niveau waardoor een enorme hoeveelheid aan debug informatie in de serverlog werd weggeschreven. De Log werd nooit leeggemaakt omdat dit geregeld werd via tijd en deze limiet nooit werd overschreden. Ik heb dit probleem opgelost door 2 zaken in de jboss-log4j.xml file te wijzigen: Ik heb het op tijd gebaseerde kuisen van de serverlog vervangen door het op bestandsgrootte gebaseerde kuisen van de serverlog. Hierbij heb ik de maximum grootte dan ingesteld op 2000 KB. Natuurlijk is dit voor een eigenlijke server niet zo handig omdat heel ver teruggaan in de tijd dan moeilijk wordt maar voor een testServer is een log van 3,5 GB ook niet handig. <!-- A size based file rolling appender --> <appender name="FILE" class="org.jboss.logging.appender.RollingFileAppender"> <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/> <param name="File" value="${jboss.server.log.dir}/server.log"/> <param name="Append" value="false"/> <param name="MaxFileSize" value="2000KB"/> <param name="MaxBackupIndex" value="1"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/> </layout> </appender> Op zich kun je ook instellen dat bepaalde niveaus niet moeten worden weggeschreven naar de serverlog. Zo heb ik alle loggings van enkele libraries pas laten wegschrijven vanaf het WARN of INFO niveau. Hierna volgt een voorbeeld van een configuratie waarbij ik de logging van org.jboss.seam pas heb laten wegschrijven vanaf het WARN niveau en niet het oorspronkelijke DEBUG niveau. Meer uitleg over de niveaus is terug te vinden bij het hoofdstuk over Log4J <!-- 22/05/08 - Limit the org.jboss.seam to INFO as its DEBUG is verbose --> <category name="org.jboss.seam"> <priority value="WARN"/> </category> 4.3.17.1.2 Deployment Deployment in een JBoss AS server werkt uiteraard goed. Alleen is bij een re-deploy veelal een herstart van de server nodig. Bij het testen van een applicatie is dit natuurlijk geen probleem al kan dit toch veel tijdverlies met zich meebrengen. Er bestaan wel systemen om hotdeployment mogelijk te maken binnen JBoss maar die waren volgens mijn collega’s te ingewikkeld om te gebruiken bij een testServer of door niet JBoss AS experts. Eindwerk Bram Gadeyne 2007-2008 70 4.3.17.2 Oracle XE Als databankomgeving gebruikte ik versie 10 van de gratis Oracle XE server. Werken op een Oracle XE server is bijna gelijk aan het werken op andere servers. Alleen bestaat er in Oracle geen oplossing voor automatisch verhogende ID’s of boolean Values. 4.3.17.2.1 Sequence Om een automatische verhoging van een ID na te bootsen moet je in Oracle gebruik maken van een sequentie. Een sequentie creëren, kan men doen aan de hand van een IDE zoals “SQL developer van Oracle” of via een SQL script. Per tabel maak je dan best een sequentie aan om mooi opeenvolgende ID’s te laten genereren. CREATE SEQUENCE "PERSOONLIJKE_OPLEIDING_SEQ" MINVALUE 999999999999999999999999999 INCREMENT BY 1 START WITH 1; 1 MAXVALUE Bij het gebruik van Persistence samen met Oracle moet een speciale definitie van de primary key worden gehanteerd om deze door Persistence automatisch te laten invullen bij een nieuwe insert. We moeten gebruik maken van de @SequenceGenerator annotatie om een referentie te leggen naar de gewenste Sequentie voor de entity. @Id @GeneratedValue(generator = "ActieSeq") @SequenceGenerator(name = "ActieSeq", sequenceName = "ACTIE_SEQ", allocationSize = 1) private Long id; 4.3.17.2.2 Boolean values In Oracle kent men geen Boolean values. Een andere oplossing bestaat erin om een veld te voorzien van het type varchar2 met als lengte 1. In dit veld kan dan een value worden opgeslagen bijvoorbeeld Y die true voorstelt en N die false voorstelt. In een Entity klasse moeten we er dan voor zorgen dat onze boolean getter en setter omgezet kan worden naar de overeenkomstige String. Hieronder het voorbeeld voor de “boolean” certificaat. Eindwerk Bram Gadeyne 2007-2008 71 private String certificaat; public boolean isCertificaat() { if (certificaat == null) { return false; } else { return certificaat.equals("Y"); } } public void setCertificaat(boolean certificaatValue) { if (certificaatValue) { this.certificaat = "Y"; } else { this.certificaat = "N"; } } Eindwerk Bram Gadeyne 2007-2008 72 5 Programmatie 5.1 Gebruikte hardware • 5.2 PC’s o Toestel AWS00369 van Dolmen. IBM Thinkcentre 1GB RAM geheugen Pentium 4 2,80 Ghz o Persoonlijke laptop IBM Thinkpad T43p 1GB RAM geheugen Pentium M processor 2,00 Ghz o Medion USB Stick voor back-up 512 MB Gebruikte software 5.2.1 Besturingssystemen 5.2.1.1 Windows XP Servicepack 2 Op de pc die ik van Dolmen kreeg werkte ik op het bekende besturingssysteem Windows XP van Microsoft. Windows XP was in dit geval uitgerust met Servicepack versie 2 waar bijvoorbeeld een betere beveiliging door een firewall en integratie met anti virus programma’s beloofd worden. 5.2.1.2 Ubuntu Linux 8.04 Op mijn persoonlijke laptop werk ik meestal in het op Linux gebaseerde besturingssysteem van Canonical genaamd “Ubuntu”. Ubuntu streeft ernaar om zo gebruiksvriendelijk mogelijk linux ter beschikking te stellen van de wereld. Ubuntu is dan ook in bijna alle talen beschikbaar. Naast Ubuntu zijn er nog vele andere Linux distributies maar Ubuntu is wel één van de beste en bekendste. Ze slagen er beetje bij beetje toch in om alle commando gebaseerde acties binnen linux om te zetten naar GUI’s. Alternatieve programma’s zoals Open Office worden er standaard op geïnstalleerd en zijn onmiddellijk gebruiksklaar wat de gebruiksvriendelijkheid ook verhoogt. Ubuntu is zeker een duidelijke verzameling voorbeelden van open-source software die niet moet onderdoen voor commerciële pakketten. Het is te downloaden via de site www.ubuntu.com. 5.2.2 Servers 5.2.2.1 Webservers 5.2.2.1.1 JBoss AS 4.2.2 GA Als Webserver gebruikte ik de JBoss AS 4.2.2 GA server waarover je bij het hoofdstuk over JBoss Server meer informatie kan vinden. Ik gebruikte de JBoss Server omdat de meeste frameworks Eindwerk Bram Gadeyne 2007-2008 73 waarvan ik gebruik maakte ook van JBoss waren en er een goede integratie van JBoss was met de eclipse IDE en de JBoss server. 5.2.2.1.2 Glassfish Glassfish gebruikte ik in het begin van mijn stage omdat ik er gebruik van had gemaakt op school. Glassfish is een Java EE server waarbij de configuratie in tegenstelling tot de JBoss server wel via een webinterface kan gebeuren. Sun heeft zijn SDK gebaseerd op de Glassfish server. 5.2.2.2 Database 5.2.2.2.1 Mysql 5.0 In het begin van mijn stage maakte ik gebruik van de Mysql server omdat ik deze gebruikte op school. Ik heb er dan ook mijn demo applicatie mee geschreven. 5.2.2.2.2 Oracle XE 10 Een vereiste van de applicatie die ik uiteindelijk schreef voor Dolmen was dat deze moest werken op een Oracle database. Daarom heb ik ook leren werken met deze versie van Oracle. Meer uitleg over de Oracle server is terug te vinden bij het gelijknamige hoofdstuk. 5.2.2.2.3 Derby Derby is een database systeem die eigenlijk in het intern geheugen gestart wordt en die op Java gebaseerd is. Ik maakte hier ook kennis mee in het begin van mijn stage. Deze server is vooral geschikt voor gebruik in een testomgeving of in een ontwikkel omgeving. 5.2.3 IDE 5.2.3.1 Eclipse Europe 3.2.2 Als IDE voor het programmeren in Java maakte ik vooral gebruik van de eclipse IDE. Deze IDE is uitbreidbaar met plugins waaronder de plugin van JBoss. Hierdoor was de eclipse IDE ook meer geschikt voor het gebruik met Seam. 5.2.3.1.1 JBoss Tools 2.0.0 GA All plugins Om te programmeren in Seam kon ik de JBoss tools installeren in eclipse. Dit is een suite van plugins die voorziet in onder andere ondersteuning voor drag and drop ontwikkeling in Richfaces en een toolkit voor het genereren van een Seam project. De JBoss Tools zijn eigenlijk de gratis plugins van JBoss voor eclipse die eclipse omtoveren naar een IDE die vergelijkbaar is met de “JBoss Developer Studio”. Deze studio is ook op eclipse gebaseerd maar is betalend waardoor er natuurlijk wel meer support voor bestaat. Meer uitleg over het gebruik en de installatie van de JBoss Tools en Eclipse is terug te vinden bij het hoofdstuk over een project starten Eindwerk Bram Gadeyne 2007-2008 74 5.2.3.2 NetBeans 6.0 Op school maakten we gebruik van de NetBeans IDE. Ik heb er gedurende mijn stage af en toe nog gebruik van gemaakt om terug te kijken naar projecten die ik in het verleden had gemaakt. NetBeans werkt echter niet goed samen met de JBoss frameworks en de JBoss server waardoor programmeren van mijn stageopdracht bij voorkeur niet gebeurde in NetBeans. 5.2.3.3 Oracle SQL Developer Als IDE om de Oracle database te bevragen maakte ik gebruik van de SQL Developer. 5.2.4 Programmeertalen 5.2.4.1 JDK 1.6 update 5 De basis van het Seam framework is de programmeertaal Java. Ik maakte dan ook gebruik van de op dat moment laatste nieuwe JDK (Java Developer Kit) versie 1.6 update 5. 5.2.4.2 Seam 2.0.2 GA De versie van de Seam library die ik gebruikte was versie 2.0.2. Meer uitleg over het Seam project is terug te vinden in het hoofdstuk over Seam. 5.2.4.3 Library’s Naast dit alles maakte ik gebruik van een aantal Librarys die in dit stageverslag ook nog uitvoerig zijn uitgelegd bij de overeenkomstige hoofdstukken. Ik som ze hieronder nog even op. Richfaces 3.2.0 GA JUnit DBUnit Persistence (Hibernate) JasperReports IText 5.2.5 Tekstverwerkers 5.2.5.1 Microsoft Word 2003 Dit stageverslag is geschreven in Microsoft Word 2003 hoewel sommige onderdelen geschreven werden in Open Office. 5.2.5.2 OpenOffice 2.4 De handleiding die ik maakte over de installatie onder Linux werd geschreven in OpenOffice 2.4 die standaard geïnstalleerd wordt in Ubuntu. OpenOffice is een opensource Office pakket die volledig compatibel is met de Microsoft Office documenten tot en met Microsoft Office 2003. Ondersteuning voor de nieuwe formaten van MS Office 2007 zal worden voorzien in OpenOffice 3. Eindwerk Bram Gadeyne 2007-2008 75 5.2.6 Beeldverwerker 5.2.6.1 The Gimp Om enkele afbeeldingen op linux te bewerken maakte ik gebruik van The Gimp die te vergelijken is met een gereduceerde open-source versie van Adobe Photoshop. 5.2.7 Varia 5.2.7.1 IReport IReport gebruikte ik voor het genereren van JasperReports. Meer informatie hierover is terug te vinden bij het gelijknamige hoofdstuk. 5.2.7.2 CWD4ALL Om het database schema opnieuw te genereren van de aangepaste oracle database maakte ik gebruik van de trial versie van deze tool. Het resultaat is het datamodel geworden. 5.2.7.3 Webbrowsers 5.2.7.3.1 Firefox Firefox was de browser die ik vooral gebruikte om tijdens het programmeren mijn applicatie uit te testen. Ik maakte er ook gebruik van de plugin Firebug om de css van mijn applicatie op een gemakkelijke manier te kunnen aanpassen en om de AJAX requests te kunnen volgen. Dit is een voorbeeld waarbij firebug gebruik wordt om AJAX requests te volgen. Als we de tabbladeren veranderen dan worden telkens AJAX requests verzonden. Eindwerk Bram Gadeyne 2007-2008 76 Dit is een voorbeeld waarbij firebug gebruikt wordt om CSS gemakkelijk te lezen. Hier bekijken we de knop personen door de optie inspect te gebruiken. De HTML code van de knop personen wordt weergegeven en de bijhorende css klassen worden rechts onderaan weergegeven. We kunnen hier dan wijzigingen in de CSS code toevoegen die dan ook onmiddellijk op de pagina wijzigingen zullen aanbrengen. 5.2.7.3.2 Microsoft Internet Explorer 7 Ter controle van de aangepaste css maakte ik gebruik van MS Internet Explorer 7. CSS opmaak wordt door de meeste browsers op een andere manier geïnterpreteerd dus controle in een andere browser was noodzakelijk. 5.3 Een nieuw project starten Hieronder zal ik wat meer uitleg geven over het starten van een nieuw Seam project. Vooraf moeten reeds een Oracle database en een JBoss Server geïnstalleerd zijn. Meer informatie over de installatie van deze 2 zijn terug te vinden in de installatie handleidingen. Eerst overlopen we de installatie van Eclipse en hoe we die dankzij de JBoss Tools kunnen omvormen tot een soortgelijke JBoss Developer Studio. Daarna worden de mogelijkheden van de drag en drop pagina ontwikkeling voor Richfaces overlopen. Eindwerk Bram Gadeyne 2007-2008 77 5.3.1 Installatie van Eclipse Op http://www.eclipse.org/downloads/ kunnen we de laatste nieuwe versie van eclipse downloaden. We kiezen hiervoor de versie voor EE developers en de correcte versie voor ons besturingssysteem. De installatie van eclipse gebeurt door het unzippen van het gedownloade zip bestand in een map naar wens. Als we deze map dan openen vinden we het eclipse.exe bestand (voor Windows) waarmee we eclipse kunnen opstarten. Eindwerk Bram Gadeyne 2007-2008 78 Bij het eerste maal opstarten van eclipse zal eclipse ons vragen waar we onze projecten willen opslaan. Hij stelt hiervoor een standaardlocatie voor. We kunnen echter een andere locatie opgeven zoals hier in dit voorbeeld. 5.3.2 Installatie van de JBoss Tools. Na de installatie van eclipse zullen we de JBoss Tools toevoegen. Deze plugins bevatten alles wat we nodig hebben voor onze eclipse omgeving om een Seam project te kunnen starten. Het bevat ook ondersteuning voor het gebruik van Richfaces. In het menu Help Software Updates kiezen we voor “Find and Install…”. In dit menu kunnen we zowel updates voor eclipse als voor geïnstalleerde plugins opzoeken en downloaden. We kiezen daarna voor “Search new features to install”. Eindwerk Bram Gadeyne 2007-2008 79 We kiezen nu voor “New Remote Site”. We vullen als naam “JBoss Tools” in en we stellen de url in op “http://download.jboss.org/jbosstools/updates/stable”. Daarna zorgen we dat deze nieuwe “Remote Site” aangevinkt staat en we klikken op “Finish”. Nu geeft eclipse ons een overzicht van de gevonden updaten. We vinken alles aan en klikken op “Next”. Eindwerk Bram Gadeyne 2007-2008 80 Daarna moeten we nog een licentie overeenkomst accepteren. We vinken “I accept the terms in the license agreement” aan en klikken op “Next”. Daarna klikken we nog op “Finish” waarna eclipse alle updates zal installeren. Eindwerk Bram Gadeyne 2007-2008 81 Eclipse vraagt ons na het downloaden of we zeker zijn dat we deze updates willen installeren. We kiezen voor “Install All”. Daarna zal ons gevraagd worden om eclipse te herstarten. 5.3.3 Installatie van de Seam Runtime Later tijdens het opzetten van ons project zullen we ook de “Seam Runtime Environment” nodig hebben. Deze is te downloaden van http://www.seamframework.org/Download. We kiezen er voor de laatste production versie. Bij ons was dit “jboss-seam-2.0.2.SP1”. We slaan de zip versie ergens op onze harde schijf op. Bijvoorbeeld ons bureaublad. De “Seam Runtime Environment” bevat alle Seam librarys en andere librarys die Seam nodig zou hebben. We unzippen deze zip-file naar een locatie op onze harde schijf. Hier koos ik bijvoorbeeld voor de “c:/” locatie. Eindwerk Bram Gadeyne 2007-2008 82 We zullen deze runtimelibrarys verder bij de creatie van een Seam project, toevoegen aan eclipse. 5.3.4 Creatie van een nieuw Seam project. We volgens hier de stappen die moeten ondernomen worden om een nieuw project op te zetten. 5.3.4.1 Een nieuw project We kiezen voor in het Filemenu van eclipse voor “New Project”. We vinden nu een aantal soorten projecten terug die we kunnen aanmaken. Wij kiezen hier onder de map Seam voor “Seam Web Project” en klikken op next. Eindwerk Bram Gadeyne 2007-2008 83 We moeten nu een nieuwe projectnaam opgeven. We kiezen onderaan voor een “Dynamic Web Project with Seam 2.0”. De Target Runtime en Server Runtime worden in de volgende hoofdstukjes verder uitgelegd. Eindwerk Bram Gadeyne 2007-2008 84 5.3.4.2 De Runtimes Daarnaast moeten we ook een Target Runtime opgeven. Hiermee bedoeld men de Runtime van onze JBoss Server. We kiezen hier een Runtime versie die overeenkomt met onze gedownloade JBoss Server. Bij ons is dit versie 4.2. We geven onze Runtime nu een naam en tonen de locatie van onze JBoss Server. We kiezen de gewenste JRE (Java Runtime Environment). Als we voorgaande instellingen correct hebben ingegeven dan kunnen we kiezen voor 3 soorten configuraties. We kiezen de default versie. We klikken hierna op Finish. Eindwerk Bram Gadeyne 2007-2008 85 Nu moeten we ook nog onze Server opgeven die we willen gebruiken om ons project op te deployen en te testen. Deployen is eigenlijk het kopiëren en installeren van een webapplicatie op een “Application Server”. Na het deployen kan een webapplicatie via een browser worden uitgevoerd. We kiezen hier ook weer voor versie 4.2. Onderaan zien we dat onze hier boven geïnstalleerde Runtime ook al geselecteerd staat. Eindwerk Bram Gadeyne 2007-2008 86 Op het volgende scherm kunnen we nog een admin paswoord en een username opgeven. Deze kunnen we ook leeg laten want we hebben geen paswoorden ingesteld voor onze Server. Daarna kunnen we nog projecten toevoegen die mogen gedeployed worden maar er zijn nog geen projecten dus we kiezen hier ook weer voor “finish” Als alles goed verlopen is dan zouden volgende instellingen te zien moeten zijn op het hoofdblad voor het aanmaken van een nieuw project. Eindwerk Bram Gadeyne 2007-2008 87 5.3.4.3 Project Facets Nu wordt ons gevraagd welke standaard librarys we willen toevoegen en configureren voor ons project. We vinken hier naast de standaard instellingen ook nog “Java Persistence” aan. Eindwerk Bram Gadeyne 2007-2008 88 5.3.4.4 De Web Module Op het volgende scherm kunnen we instellingen instellen die te maken hebben met de Web Module van onze webapplicatie. De “Context Root” zal hat adres zijn waar we naartoe zullen kunnen surfen die na het serveradres komt. Zo is bijvoorbeeld “SeamExample” de “Context Root” in het adres http://localhost/SeamExample. 5.3.4.5 De JPA Module Het volgende scherm vraagt ons de instellingen voor JPA. We kunnen er een connectie toevoegen naar onze oracle database. We kiezen voor een “Generic JDBC Connection”. Daarna geven we een naam op voor onze connectie bijvoorbeeld “oracle local”. Daarna moeten we een driver voor de Oracle XE connectie opgeven. We kiezen daarvoor versie 10 en moeten nu de driver toevoegen. Deze is bij een standaard installatie van oracle te vinden op de locatie “C:\oraclexe\app\oracle\product\10.2.0\server\jdbc\lib”. Je kan kiezen voor driver ojdbc_14 of ojdbc14_g. Ik kies hier altijd versie ojdbc14_g. We installeren JPA om op die manier gemakkelijk later entity klassen met eclipse te kunnen laten genereren. Er zal hiervoor een datasource file aangemaakt worden in ons project die een beschrijving bevat van hoe het project verbinding kan maken met de database. Op de webserver zullen we later zelf nog een datasource moeten instellen. Meer informatie hierover is terug te vinden in de installatie handleiding. Eindwerk Bram Gadeyne 2007-2008 89 Daarna kunnen we de geïnstalleerde driver kiezen als te gebruiken driver en kunnen we op “ok” klikken. Als we nu alle gegevens correct hebben ingevuld dan kunnen we via test connection testen of onze connectie effectief werkt. Eindwerk Bram Gadeyne 2007-2008 90 We zorgen dan dat de instellingen op het hoofdscherm als volgt staan ingevuld. Eindwerk Bram Gadeyne 2007-2008 91 5.3.4.6 De JSF Module Op het volgende scherm kunnen we configuraties uitvoeren voor JSF. Hier staat normaalgezien alles ingevuld naar wens. Onderaan zien we dat JSF de extensie .xhtml zal omzetten naar de extansie .seam. Hierdoor zullen alle pagina’s die opgeroepen worden met de .seam extensie door de Faces Servlet worden gerenderd alvorens ze door te sturen. 5.3.4.7 De Seam Module Nu moeten we het Seam gedeelte invullen. Hier zullen we onze Runtime moeten instellen. Zorg ervoor dat de versie ingesteld staat op versie 2.0! Eindwerk Bram Gadeyne 2007-2008 92 We zorgen dat de instellingen overeen komen zoals in onderstaande afbeelding. Er wordt hier nogmaals gevraagd om de connectie met de database op te geven en het database type te selecteren. Ik heb voor dit voorbeeld gebruik gemaakt van dezelfde database als die van het project ComMaS. De schema naam hiervan was COMMAS. Dit kan eventueel ook leeg gelaten worden. Eindwerk Bram Gadeyne 2007-2008 93 Daarna klikken we op finish en ons project wordt voor ons aangemaakt. Men vraagt ons nog of we het Seam perspectief willen openen. Hier kiezen we voor ja. 5.3.5 Het project starten Seam heeft nu voor ons een nieuw project aangemaakt met behulp van de seam-gen tool. We zien links in eclipse een overzicht van de 4 delen van ons project. Het SeamExample gedeelte bevat alle inhoud die nodig is voor het webgedeelte van onze applicatie. SeamExample-ear bevat alle overkoepelende instellingen en librarys. SeamExample-ejb zal alle EJB’s en klassen van onze applicatie bevatten. Daarnaast hebben we ook nog SeamExample-test waarin we onze testen zullen kunnen aanmaken. We kunnen dit project reeds uitvoeren. We selecteren ons SeamExample-ear project en klikken dan op het groene pijltje die in de voorgaande afbeelding terug te vinden is in de bovenste werkbalk. Men vraagt ons op welke server we dit project willen uitvoeren. We kiezen daarvoor onze geïnstalleerde JBoss 4.2 server. Daarna vraagt men ons welke modules we willen deployen. We zorgen dat alle modules toegevoegd worden. Als we geen datasource hebben geïnstalleerd op de server kunnen we ook voorlopig de door Seam gegenereerde datasource deployen. Die is terug te vinden in het ear project onder resources. We kunnen deze deployen door “Deploy To Server” te kiezen nadat we er met de rechtermuisknop op hebben geklikt. Na het starten van de server zien we in de console onderaan hoe onze server opgestart wordt. Nadat de server opgestart is kunnen we binnen de browser die zich in eclipse ondertussen geopend heeft surfen naar http://localhost:8080/SeamExample. We krijgen dan onderstaande voorbeeldwebsite te zien. Dit is een demoapplicatie van de Seamgen waarin je al enkele richfaces componenten te zien krijgt. Het gaat hier vooral om een menubar en panels. We kunnen reeds fictief inloggen op deze demosite. Dit toont de handige werking van het Identity object. Hierover is meer informatie te vinden bij het hoofdstuk over Seam authenticatie. Eindwerk Bram Gadeyne 2007-2008 94 5.3.6 Werken met de JBoss Tools Na het genereren van ons nieuwe project werd ons gevraagd of we het “Seam perspectief” wilden openen. Dit is eigenlijk een layout voor eclipse waarbij de JBoss Tools zichtbaar worden. De JBoss Tools voorzien in enkele functionaliteiten die toegevoegd worden aan eclipse om een betere ondersteuning voor de JBoss producten te voorzien. Onderaan vinden we bijvoorbeeld het tabblad “JBoss Server View” waarin we allerlei configuraties aan de server kunnen veranderen. 5.3.7 Richfaces drag and drop demo Ik zal hierna nog een klein voorbeeld geven voor de drag and drop mogelijkheden voor richfaces. Stel dat we op onze home pagina een calender componenten willen toevoegen dan kunnen we dat in een aantal klikken doen. In de WebContent map vinden we het bestand home.xhtml terug. Dit bestand wordt geopend aan de hand van een template waarover in dit stage verslag onder “templating in JSF” meer terug te vinden is. We zullen op de home pagina een calendar toevoegen. We zien hieronder het geopende home.xhtml bestand. We zien de HTML, JSF en Richfaces code en onderaan een WYSIWYG editor die ons onmiddellijk een overzicht van de webpagina geeft. Eindwerk Bram Gadeyne 2007-2008 95 We slepen nu de calendar die terug te vinden is in het menu recht onder JBoss Richfaces naar een gewenste locatie in onze code. Tijdens het slepen toont men een scherm waarin we alle attributen al kunnen invullen. We doen dit echter niet en laten dus alle standaardwaarden staan door gewoon op “Finish” te klikken. In dit scherm konden we bijvoorbeeld al de value van het calendar object koppelen aan een waarde van één van onze backing beans. Eindwerk Bram Gadeyne 2007-2008 96 Als we dan nu kijken naar de WYSIWYG editor zien we dat er een calender object werd toegevoegd en in de code merken we de “<rich:calendar></rich:calendar>” tags op. Als we nu deze pagina opslaan en we onze webpagina refreshen in de browser binnen eclipse zien we onmiddellijk onze wijzigingen in de effectieve webpagina. Hotdeployment op een JBoss Server werkt op niveau van webpagina’s alhoewel we toch ook af en toe een server restart zullen moeten doen. Als we EJB’s of andere zaken zouden willen wijzigen moeten we wel een volledige server restart doen. Eindwerk Bram Gadeyne 2007-2008 97 5.4 Algoritmes Om de TreeNode voor de RichTree componenten op te vullen maakte in gebruik van een recursieve methode. Hoogste nodes in de tree’s was steeds het type van de onderliggende competenties. Daaronder zaten dan steeds competenties die op hun beurt weer competenties konden hebben. Om nodes aan te maken moest een node steeds een uniek nummer bevatten op zijn niveau. Deze werd bijgehouden in de counter en werd verhoogd na elke toevoeging van een nieuwe node. treeNode is de rootNode van de tree. Onder treeNode werden steeds TreeNodeImpl objecten toegevoegd met als data een type. Na het toevoegen van een type werden dan alle competenties die geen parentcompetentie hadden toegevoegd onder dit type. Onder deze competententies werden dan recursief competenties toegevoegd die als parentcompetentie de toegevoegde competentie hadden. /** The tree node. */ @SuppressWarnings("unchecked") private TreeNode treeNode; /** The counter. */ private Integer counter; Eindwerk Bram Gadeyne 2007-2008 98 @SuppressWarnings("unchecked") public void loadTree() { try { counter = 1; treeNode = new TreeNodeImpl(); treeNode.setData("Types"); List lijst = typeService.getAllOrderedByTypenaam(); for (int i = 0; i < lijst.size(); i++) { Type type = (Type) lijst.get(i); TreeNode node = new TreeNodeImpl(); node.setData(type); treeNode.addChild(counter, node); counter = counter + 1; loadCompetenties(type, node, counter); counter = counter + 1; } try { log.info("loadTree uitgevoerd."); } catch (NullPointerException e) { } } catch (RuntimeException e) { log.error("kon loadTree niet uitvoeren" + e.getMessage()); } } @SuppressWarnings("unchecked") public void loadCompetenties(Type type, TreeNode node, Integer counter) { List<Competentie> lijst = competentieService.getByType(type); Iterator<Competentie> it = lijst.iterator(); while (it.hasNext()) { Competentie comp = it.next(); if (comp.getParentid() == null) { TreeNode subNode = new TreeNodeImpl(); subNode.setData(comp); node.addChild(counter, subNode); counter = counter + 1; loadChildCompetenties(comp, subNode, counter); counter = counter + 1; } } } @SuppressWarnings("unchecked") public void loadChildCompetenties(Competentie competentie, TreeNode node, Integer counter) { List<Competentie> lijst = competentieService .getByParentCompetentie(competentie); Iterator<Competentie> it = lijst.iterator(); while (it.hasNext()) { Competentie comp = it.next(); TreeNode subNode = new TreeNodeImpl(); subNode.setData(comp); node.addChild(counter, subNode); counter = counter + 1; loadChildCompetenties(comp, subNode, counter); counter = counter + 1; } } Eindwerk Bram Gadeyne 2007-2008 99 6 Bespreking van het programma 6.1 Gebruikershandleiding In deze gebruikershandleiding geven we wat meer uitleg bij de schermen die beschikbaar zijn in de applicatie. Eerst komen een aantal algemene zaken die voor elke gebruiker hetzelfde zijn. Daarna volgen vooral de uitleg van de schermen zoals een personeelsverantwoordelijke of administrator ze zullen zien. Voor de andere gebruikers zal er steeds uitgelegd worden wat ze niet kunnen uitvoeren of hoe sommige zaken voor hen werken. 6.1.1 Gebruikerstypes In deze applicatie maken we gebruik van 5 gebruikerstypes. Het is zo dat elke gebruiker die zich hoger in de hiërarchie bevindt ook steeds alles moet kunnen doen wat een gebruiker onder hem kan uitvoeren. • • • • • Administrator o Dit is de hoofdgebruiker die alle rechten heeft over de volledige applicatie. Hij is ook de enige die andere gebruikers kan benoemen tot administrator. Personeelsverantwoordelijke o Heeft alle rechten over de gehele applicatie. De hoofdtaak van de personeelsverantwoordelijk is echter het opstellen van de functiebeschrijvingen en het beheren van de gebruikers. Personeelssecretariaat o Het personeelssecretariaat beheert vooral opleidingen binnen Dolmen en kan gebruikers toevoegen aan sessies. Chef o Kan medewerkers toevoegen en ze aanduiden als zijn medewerkers. De Chef kan medewerkers beheren die aangeduid zijn als zijn medewerkers. Daarnaast kan een chef ook functiebeschrijvingen en opleidingen beheren. Medewerker o De medewerker kan zijn eigen voortgang op vlak van competenties volgen en kan PO verslagen nalezen en er opmerkingen toevoegen. De medewerker kan ook zijn eigen acties volledig beheren. 6.1.2 Algemeen We bespreken hier de onderdelen van de applicatie die voor alle gebruikers dezelfde werking hebben. Het gaat hier meestal niet over effectieve schermen maar over handelingen die op dezelfde manier kunnen gebeuren. 6.1.2.1 inloggen Elke gebruiker kan zijn/haar gegevens invullen bij het surfen naar de webpagina. Standaard hebben alle gebruikers het paswoord “paswoord” die wel door een beheerder kan worden aangepast. Eindwerk Bram Gadeyne 2007-2008 100 We kunnen een gebruikersnaam onthouden om de volgende keer gemakkelijk onder dezelfde naam opnieuw in te kunnen loggen. Dit doen we door het vinkje naast onthouden aan te vinken. Het kan ook zijn dat we na surfen naar een bepaalde URL in onze applicatie ook dit inlogscherm te zien krijgen. Dit komt omdat we geen enkele pagina kunnen bezoeken waar we geen rechten toe hebben. Zelfs niet als we de juiste URL ervoor kennen. 6.1.2.2 Uitloggen Rechts bovenaan in het menu vinden we een knop om onszelf uit het programma uit te loggen. We krijgen hierna opnieuw de mogelijkheid om onszelf in te loggen in het systeem. 6.1.2.3 Paswoorden wijzigen We kunnen een paswoord wijzigen door na het inloggen op de knop “paswoord wijzigen” in het menu te klikken. We moeten dan ons oud paswoord ter verificatie en het nieuwe gewenste paswoord invullen. Eindwerk Bram Gadeyne 2007-2008 101 6.1.2.4 Taal wijzigen Het programma is vertaald in de 3 talen Nederlands, Frans, Engels. Al naargelang waar de webapplicatie geopend wordt zal de respectievelijke taal worden gebruikt. Als we een andere taal wensen te gebruiken dan kunnen we in het menu op de gewenste taal klikken. 6.1.2.5 Werken met lijsten Het programma bestaat bijna volledig uit lijsten die bepaalde gegevens weergeven. Aan zo’n lijsten kunnen we meestal gegevens toevoegen, verwijderen of er gegevens van aanpassen. Op sommige plaatsen in ons programma is het mogelijk om van sommige items in een lijst de detailweergave te openen. 6.1.2.5.1 Toevoegen Een nieuw item toevoegen kunnen we doen door links onder een lijst op de knop “nieuw” te klikken. We zien hier het voorbeeld van een lijst waarbij we personen kunnen toevoegen. Als we alle gegevens correct hebben ingevuld dan kunnen we nadien op de knop “toevoegen” klikken. Daarna zal het gewenste item toegevoegd worden aan de lijst. Als we foutieve gegevens invullen zal het programma ons daarover waarschuwen en zullen we die eerst moeten aanpassen voordat we de gegevens zullen kunnen opslaan. 6.1.2.5.2 Aanpassen Een voorbeeld voor het aanpassen en verwijderen van item uit een lijst. Eindwerk Bram Gadeyne 2007-2008 102 We zien in de lijst een kolom met als naam opties. In deze kolom zullen we steeds acties kunnen terugvinden die we kunnen uitvoeren voor het item van de bijhorende rij. Hier hebben we bijvoorbeeld de opties “aanpassen” gekozen voor de gebruiker met als gebruikersnaam “gadeynebram”. Onderaan de lijst zal dan steeds een paneel verschijnen waar we de waarden van de geselecteerde rij kunnen aanpassen. De wijzigingen doorvoeren kunnen we doen door op de knop “opslaan” te klikken. Onderaan het paneel kunnen nog extra opties beschikbaar worden voor de geselecteerde rij. In dit geval kunnen we voor de geselecteerde gebruiker het paswoord herzetten door op de knop “paswoord herzetten” te klikken. Als we foutieve gegevens invullen zal het programma ons daarover waarschuwen en zullen we die eerst moeten aanpassen voordat we de gegevens zullen kunnen opslaan. 6.1.2.5.3 Verwijderen Als we in een lijst de mogelijkheid hebben om een rij te verwijderen dan zal, na het klikken op deze optie, ons gevraagd worden of we deze rij daadwerkelijk willen verwijderen. Eindwerk Bram Gadeyne 2007-2008 103 Door op de knop “Ok” te klikken wordt de bijhorende rij verwijderd. 6.1.2.5.4 Detailweergave Van sommige onderdelen zien we graag een detail weergave. Bij ons voorbeeld van personen is de detailweergave heel uitgebreid. Om een detailweergave op te roepen klikken we op een kolomwaarde die vet gedrukt staat. Bij personen is dit bijvoorbeeld de kolom “persnr”. Door op deze vetgedrukte waarde te klikken wordt voor ons de bijhorende detailweergave geopend. Het is mogelijk dat we in een detailweergave ook weer lijsten terugvinden waar we op hun beurt een detailweergave van kunnen opvragen. Terugkeren naar vorige schermen kunnen we dan doen door op de knop “terug” te klikken die onderaan links op deze pagina’s te vinden is. 6.1.2.5.5 Door gegevens scrollen Een lijst heeft standaard een lengte van 10 regels. De beheerder van de applicatie kan dit eventueel wijzigen. Om te kunnen navigeren in een lijst kunnen we onder deze lijst klikken op de gewenste pagina of op de pijltjes die ons door de lijst laten navigeren. 6.1.2.5.6 Zoeken in gegevens In sommige lijsten is er een mogelijkheid ingebouwd om te kunnen zoeken. Hiervoor is boven een lijst een paneel “zoeken” voorzien waar we dan op enkele kolommen kunnen zoeken. Als we gegevens in een zoekveld intypen zal de lijst automatisch verkleind worden met gegeven die voldoen aan de zoekterm. De zoekterm verloopt volgens het patroon %zoekterm% waarbij % wil zeggen 0 of meer tekens. De zoekterm is wel hoofdletterafhankelijk. Eindwerk Bram Gadeyne 2007-2008 104 6.1.2.6 Werken met Treeviews Treeviews zijn heel handige tools om een boomstructuur weer te geven. In deze applicaties worden ze vooral gebruikt om Competenties te beheren. 6.1.2.6.1 De Opbouw We zien in onderstaande figuur hoe een tree is opgebouwd. We zien 2 “types” die een groepering maken van competenties. In dit geval zijn dit “SE” en “WEB”. Types worden voorgesteld door een mapje. Als we op een pijltje klikken dan worden alle onderliggende items geladen. Onder een Type vinden we tandwieltjes en sleutels. Een tandwiel is een competentiegroep. Een sleutel is een deelcompetentie van zo’n competentiegroep. Als we een node selecteren dan worden onder de tree soms opties zichtbaar die het toelaten om zo’n node te bewerken. Opslaan van de wijzigingen kan gebeuren door 1 maal te klikken op een node. 6.1.2.6.2 Dubbele Trees Op sommige pagina’s vinden we ook Trees terug die een splitsing maken tussen items die door de geselecteerde detailview in gebruik zijn of net niet. Door op een type te klikken worden alle competentiegroepen voor zit type verwijderd of toegevoegd aan de detailview. Hetzelfde geldt Eindwerk Bram Gadeyne 2007-2008 105 voor de selectie van een competentiegroep. Voor sommige competenties kunnen we dan soms nog extra opties invullen maar dit is afhankelijk van de locatie in het programma. 6.1.3 Het admin paneel De eerste grote groep van gebruikersschermen zitten vervat onder de schermen van het adminpaneel. Ze hebben de functie om globale configuraties te doen dan de configuratie op het niveau van één enkele gebruiker. Personen uit de medewerker gebruikersgroep hebben geen toegang tot alle schermen in het adminpaneel. Personen uit de personeelssecretariaatsgroep hebben enkel rechten op het onderdeel “opleidingen”. 6.1.3.1 Gebruikers beheren Het eerste tabblad geeft ons een overzicht van personen. Gebruikers kunnen er toegevoegd, verwijderd of aangepast worden. 6.1.3.1.1 Allen Bij het toevoegen of aanpassen van gegevens gebeurt er een foutcontrole. Als er iets mis ingevuld wordt dan zal ons dat gemeld worden met een bericht die in het rood terug te vinden is rechts van het foutieve veld. Bij het niet invullen van het emailadres zal het programma automatisch een e-mailadres maken in de vorm van [email protected]. We kunnen een ander adres opgeven door hier zelf iets in te vullen. Een gebruiker kan enkel andere gebruikers promoveren tot een gebruikersgroep die lager is of gelijk aan de groep waarin ze zich zelf bevinden. In de lijst met medewerkers kan er gezocht worden op de naam en de voornaam van een medewerker. Eindwerk Bram Gadeyne 2007-2008 106 6.1.3.1.2 De chef Een chef heeft echter een ander beeld. Deze persoon is enkel geïnteresseerd in zijn eigen medewerkers en de medewerkers die momenteel geen chef hebben. De personen die onderaan te zien zijn, zijn de personen die momenteel geen chef hebben. Hier gaat het dus enkel om “vrije medewerkers”. Door op de knop toevoegen te klikken kan een chef een medewerker toevoegen als zijn medewerker. Een Chef kan personen aanpassen waarvan hij chef is. Daarnaast kan een chef personen ook weer verwijderen uit de lijst van zijn medewerkers. Een chef kan dus geen personen effectief en blijvend uit het systeem verwijderen. Eindwerk Bram Gadeyne 2007-2008 107 6.1.3.2 Opleidingen beheren In dit Tabblad kunnen we de opleidingen beheren die binnen Dolmen worden ingericht. Alle gebruikers die toegang hebben tot het adminpaneel hebben de toegang tot dit opleidingspaneel. We zien in deze lijst ook welke sessies er al zijn ingericht voor een bepaalde opleiding. Door op de titel van een opleiding te klikken kunnen we diens gegevens en sessies aanpassen. We zien ook dat we voor een opleiding bijhorende competenties kunnen toevoegen die verworven kunnen worden door een opleiding te volgen. Eindwerk Bram Gadeyne 2007-2008 108 Voor een sessie kunnen we een maximum aantal deelnemers instellen. In de detailweergave van een sessie kunnen we gebruikers toevoegen aan zo’n sessie die dan deze sessie zullen bijwonen. Als het aantal maximum toe te voegen personen overschreden wordt, dan zal er een bericht getoond worden. In dit voorbeeld hieronder zien we links de tekst “Er zijn geen plaatsen meer vrij in deze sessie” verschijnen. Voor elke persoon in een sessie kunnen we ook nog aanvinken of deze opleiding een certificaat oplevert en/of op de CV zal worden weergegeven. Eindwerk Bram Gadeyne 2007-2008 109 6.1.3.3 Functiebeschrijvingen beheren Functiebeschrijvingen kunnen beheerd worden door alle groepen die toegang hebben tot het adminpaneel behalve door de leden van de groep personeelssecretariaat. In dit lijstscherm kunnen we functiebeschrijvingen toevoegen. Door op omschrijving te klikken kunnen we de detailweergave van een functiebeschrijving bekijken en aanpassen. Onderaan de lijst vinden we ook een knop “rapport” terug waarmee we een rapport kunnen ophalen in PDF-formaat die alle functiebeschrijvingen bevat. In de detailweergave vinden we enkele detailgegevens in verband met een functiebeschrijving. Die kunnen we aanpassen en opslaan door op de knop aanpassen te klikken onderaan de pagina. We kunnen voor een functiebeschrijving taken toevoegen die zullen moeten worden uitgevoerd door de functionaris. Competenties die benodigd zijn kunnen worden toegekend. We kunnen de details van een competentie in gebruik een minimum score en een prioriteit invullen voor een competentiegroep of voor een competentie. Eindwerk Bram Gadeyne 2007-2008 110 Als laatste kunnen we onderaan de pagina ook nog eens de gebruikers zien die momenteel deze functie hebben en we kunnen andere gebruikers eraan toevoegen. Onderaan de pagina is er een mogelijkheid voorzien om een samenvattend rapport van de functiebeschrijving in pdf-formaat op te halen. Eindwerk Bram Gadeyne 2007-2008 111 6.1.3.4 Competenties beheren Competenties kunnen beheerd worden door alle groepen die toegang hebben tot het adminpaneel behalve door de groep personeelssecretariaat. Competenties beheren gebeurt via een tree. Navigeren hierin kan door op de pijltjes te klikken. Om een type of een competentie te bewerken kruisen we diens vinkje aan. Het item blijft geselecteerd totdat we een ander item selecteren. Voor het geselecteerde item komt onmiddellijk de optie om die aan te passen. We kunnen ook kiezen om een nieuw type toe te voegen, een nieuwe competentie toe te voegen of het geselecteerde item en alle onderliggende items te verwijderen. Zolang we geen nieuw item selecteren zullen we competenties kunnen toevoegen onder het laatste geselecteerde type of competentie. Pas op! Bij het verwijderen van een competentie of type worden ook alle overeenkomstige items elders in het programma verwijderd. Dit zijn dan bijvoorbeeld persoonlijke competenties van medewerkers, opleiding competenties of verwachte competenties uit functiebeschrijving. We krijgen wel een waarschuwing als we een item willen verwijderen. Eindwerk Bram Gadeyne 2007-2008 112 6.1.3.5 Mail Een personeelsverantwoordelijke of administrator kan in ons programma de opdracht geven om mails te verzenden. Deze mails houden herinneringen in voor acties waarvan de deadline binnen de komende 3 dagen afloopt. Deze aantal dagen parameter kan ook door een beheerder van het programma worden aangepast. De herinnering voor een actie wordt slechts 1 maal verzonden. 6.1.4 Het Gebruiker Menu Het gebruikers menu opent de detailweergave van de huidig ingelogde gebruiker. Deze detailweergave is eveneens de detailweergave die we verkrijgen wanneer we de detailweergave van een persoon uit de lijst van personen in het adminpaneel opvragen. De voorbeelden die we hier zullen volgen zijn er waarbij een personeelsverantwoordelijke, een administrator of een chef wijzigingen aanbrengt bij de persoon dummy1. Dit omdat deze personen meestal alle rechten hebben om wijzigingen aan te brengen. Een medewerker kan meestal enkel zaken raadplegen of heeft geen toegang tot bepaalde tabbladen. Ook kan een medewerker sommige rapporten afdrukken. De personen uit de groep personeelssecretariaat kunnen enkel het tabblad details raadplegen. De overige tabbladen zullen door hen nooit gebruikt moeten worden. 6.1.4.1 Details Op het details tabblad krijgen we een overzicht van de gegevens van de geselecteerde of ingelogde gebruiker. We zien ook de functies die een gebruiker al heeft gehad, momenteel heeft of in de toekomst graag zou verkrijgen. Eindwerk Bram Gadeyne 2007-2008 113 6.1.4.1.1 De personeelsverantwoordelijke, administrator en chef Deze personen kunnen functies toevoegen of verwijderen van een persoon. Ze kunnen tevens instellen of een functie een vorige, huidige of toekomstige functie is. 6.1.4.1.2 De medewerker en leden van de personeelssecretariaat groep Deze personen zien enkel de detailweergave van hun gegevens en een lijst van hun functies. Zij kunnen deze lijst echter niet aanpassen. Ze kunnen wel de omschrijving van de functie raadplegen. 6.1.4.2 PO PO verslagen worden ingevuld door de chefs van hun medewerkers. Ze kunnen ook worden aangepast door de administrators of personeelsverantwoordelijken. Een medewerker zelf kan deze wel raadplegen maar enkel het veld “opmerkingen” aanpassen. Als een chef een persoonlijk overleg heeft gehouden met één van zijn medewerkers moet hij daarvoor een verslag bijhouden. In dit menu vinden we een overzicht van de verslagen en kunnen we verslagen toevoegen. Eindwerk Bram Gadeyne 2007-2008 114 Als we nu de detailweergave van een item een po verslag openen kunnen we deze invullen. De detailweergave kunnen we openen door op de titel van het verslag te klikken. We kunnen er de besproken onderwerpen invullen. De zaken die als resultaat van de vergadering in orde moeten worden gebracht, worden ingevuld bij “te doen”. Er is een veld opmerking voorzien waarin een medewerker nog opmerkingen over de vergadering kan toevoegen. Opslaan van al deze gegevens kan gebeuren door op de knop opslaan te klikken. We kunnen de wijzigingen in het veld “titel” en “opmerkingen” ook negeren door op de knop “annuleren” te klikken. 6.1.4.3 Klantentevredenheid De klantentevredenheidsonderzoeken zijn enkel toegankelijk voor de personen uit de groepen chef, administrator of personeelsverantwoordelijke Als een project afgelopen is, kunnen klanten soms een klantentevredenheid opsturen. Een chef kan deze dan toevoegen als referentie voor de medewerker. De functie waarin de medewerker het project uitwerkte moet worden geselecteerd via het lijstje met de functies die de medewerker uitgevoerd heeft. De datum kunnen we invullen aan de hand van het kalendertje dat verschijnt. Na het toevoegen van de klantentevredenheid kunnen we een bestand uploaden door op het groene icoontje te klikken. Eindwerk Bram Gadeyne 2007-2008 115 Daarna wordt ons dan gevraagd om een bestandslocatie op te geven. Door op bladeren te klikken kunnen we deze locatie opgeven. Als we daarna op uploaden klikken dan wordt het bestand naar de server weggeschreven. Nadat we het bestand hebben geüpload kunnen we dit ook terug downloaden door op het witte icoontje naast bestand te klikken. We kunnen het verwijderen door op het rode icoontje te klikken naast bestand. 6.1.4.4 Acties Het menu Acties is beschikbaar voor alle gebruikers behalve de gebruikers uit de groep personeelssecretariaat. Acties zijn meestal opdrachten die moeten vervuld worden tegen een bepaalde deadline. In dit menu kunnen beheerd worden. De medewerker heeft hier net als alle andere gebruikers alle rechten op. We kunnen van alle acties een lijst afdrukken door op de knop rapport te klikken. Eindwerk Bram Gadeyne 2007-2008 116 Als we op de titel van een actie klikken wordt de detailweergave geopend waar we nog meer informatie over de actie kunnen invullen. Opslaan van deze wijzigingen kunnen we opslaan door op de knop “opslaan” te klikken. 6.1.4.5 Opleiding Tot dit menu hebben alle gebruikers toegang behalve diegene die tot de groep personeelssecretariaat behoren. Een medewerker kan op deze pagina enkel gegevens raadplegen en bestanden downloaden. Hij kan ze dus niet wijzigen of nieuwe toevoegen. We krijgen een overzicht van persoonlijke opleidingen die een medewerker gevolgd heeft. Ook hiervoor kunnen we zoals bij de klantentevredenheden bestanden uploaden als bewijs van de gevolgde opleiding. Deze bestanden worden dan certificaten genoemd. Onderaan zien we een overzicht van de opleidingen die een medewerker gevolgd heeft of zal volgen binnen Dolmen. Deze opleidingen kunnen hier echter niet worden toegevoegd maar zijn het resultaat van het toevoegen van een medewerker aan een sessie van een opleiding. Zie het onderdeel opleidingen in het adminpaneel voor meer informatie. We kunnen ook een overzichtsrapport laten afdrukken van dit alles door op de knop “rapport” te klikken. Eindwerk Bram Gadeyne 2007-2008 117 6.1.4.6 Competenties De chefs, administrators en personeelsverantwoordelijken kunnen competenties van een medewerker aanpassen en toevoegen of verwijderen. Een medewerker kan enkel een overzicht van zijn verkregen competenties raadplegen en er de details van weergeven. Hij kan niks aanpassen. Een medewerker beschikt over bepaalde competenties. Deze kunnen we via dit tabblad toevoegen of verwijderen. We kunnen er ook een bepaalde score aan geven of een bepaalde gewenste score. Een voorbeeld hiervan is het aanpassen van de gewenste score na een PO of een wens om een andere functie binnen het bedrijf te kunnen verkrijgen. Ook van de competenties kunnen we een overzicht laten afdrukken in de vorm van een rapport. Eindwerk Bram Gadeyne 2007-2008 118 Eindwerk Bram Gadeyne 2007-2008 119 6.2 Installatiehandleiding Windows Tijdens mijn stage werd me gevraagd om een handleiding te maken voor de installatie van mijn applicatie. Het resultaat ervan kunt u terugvinden in bijlage 1. 6.3 Installatiehandleiding Linux Naast de installatie handleiding voor Windows maakte ik er ook één voor Linux. Dit deed ik niet alleen om mijn passie voor Linux tijdens mijn stage te kunnen gebruiken, maar ook om de platformonafhankelijkheid van mijn applicatie uit te kunnen testen. Het resultaat is terug te vinden in bijlage 2. Eindwerk Bram Gadeyne 2007-2008 120 7 Conclusies Seam’s like future, de titel die ik koos toen ik begon met schrijven aan dit eindwerk. Voor mij was het een hele ervaring om te programmeren in een gloed nieuw framework tevens een JEE omgeving. De snelheid waarmee het project in het begin vorderde en er dus al bruikbare functionaliteit voor de gebruikers beschikbaar was, vond ik fenomenaal. Het ging in dat stadium vooral om lijstschermen met CRUD (create, read, update, delete) mogelijkheden. Seam voorziet zelfs een mogelijkheid om CRUD schermen te genereren van een bestaande database. Dit deed ik echter niet omdat ik niet echt geloof in het gebruik van automatisch gegenereerde code. Als programmeur wordt alles voor jou gemakkelijk gemaakt door wizards die je voorzien van allerlei functionaliteiten. Ik denk dat je dan als programmeur op een gegeven moment wel gaat vervreemden van je eigen programmeertaal. Ik koos er dan ook bewust voor om zelf alle webpagina’s te schrijven. Één van mijn wensen van een stage was immers dat ik veel zaken zou bijleren. Naar mate ik echter vorderde in mijn stageopdracht, en er dus ook moeilijkere functionaliteiten moesten worden toegevoegd, hoe moeilijker en trager het ontwikkelen van de applicatie verliep. De weinige documentatie waarover ik beschikte kon me bij sommige problemen niet onmiddellijk helpen. Ik heb dan ook veel beroep moeten doen op forums of blogs waar ik soms dagenlang op heb zitten zoeken naar de oplossing voor een probleem. Documentatie van de Seam componenten is ook niet echt uitgebreid. Meestal moest ik mij tevreden stellen met een miniem voorbeeldje die in sommige gevallen werkte en in andere dan weer niet. Veelal waren problemen in het algemeen bekend maar waren oplossingen ver te zoeken. Ondanks het soms lang zoeken naar een oplossing voor een probleem, heb ik toch voor bijna elk probleem een oplossing gevonden. Alleen het probleem waarbij ik automatisch mails moest verzenden heb ik nooit kunnen oplossen. Soms heb ik gebruik moeten maken van libraries die helemaal niet van Seam zijn. Gelukkig laat Seam het gebruik van andere libraries toe waardoor het opvangen van problemen op die manier toch goed waren. Ik ben overtuigd dat Seam met zijn visie over zijn framework een stap in de goede richting heeft gezet. Met de Java standaarden wordt in sommige frameworks geen rekening gehouden waardoor compatibiliteit soms een probleem vormt. Seam wil deze standaarden net wel gebruiken en voorziet een goede integratie tussen de standaarden. De componenten waarin Seam voorziet en die mogelijkheden als mailen, authenticatie en logging beschikbaar maken, zijn volgens mij ook een goede stap in de juiste richting. Algemeen gezien zijn deze componenten gebaseerd op frameworks die veel gebruikt worden maar is de integratie met de Java standaarden verbeterd. Spring is hier ook een voorbeeld die voorziet in deze mogelijkheden alleen werkt het soms naast de standaarden. Natuurlijk kent Seam wel het probleem dat onder de kap van de mooie visie en de gebruiksvriendelijkheid er ook nog wat moet gesleuteld moet worden aan de effectieve uitwerking en stabiliteit. Sommige componenten binnen Seam kunnen niet goed met elkaar samenwerken en hebben af en toe te kampen met bugs uit het frameworks. Ik geloof er echter in dat wanneer Seam meer zal gebruikt worden deze bugs zullen verdwijnen en het framework daardoor veel aan stabiliteit zal winnen. Eindwerk Bram Gadeyne 2007-2008 121 Seam’s like future vond ik dus een goede naam voor dit eindwerk en is tevens toepasbaar op de conclusie. Het kan gelezen worden in 2 contexten. De ene met de positieve klank die zegt dat Seam toekomst in zich heeft. De creatie van de nieuwe standaard webbeans die op Seam is gebaseerd is daar een mooi voorbeeld van. De andere iets negatievere omdat Seam momenteel misschien nog niet volledig klaar is om al in echt grote applicaties te worden gebruikt. Wanneer het framework na enkele jaren van gebruik aan stabiliteit heeft gewonnen dan zal het pas echt klaar zijn om door de weide wereld gebruikt te worden. Eindwerk Bram Gadeyne 2007-2008 122 8 Kritische Reflectie Het begin van mijn stage bestond uit het analyseren van de doelen van de vele frameworks die ik ging moeten gebruiken, en hoe ik ermee kon werken. Ik heb telkens geprobeerd om zaken op te zoeken naar gelang ik die nodig had bij de uitwerking van de applicatie of na feedback van mijn mentor. Het probleem hierbij was dat ik soms een groot aantal webpagina’s of klassen heb moeten aanpassen. Dit om toch een andere maar meestal betere oplossing of framework te gebruiken voor een bepaald probleem. Ik geef hieronder 3 voorbeelden Ten eerste een voorbeeld uit het begin van mijn stage. Ik voerde soms controles uit op mijn code om bepaalde statussen van variabelen tijdens het uitvoeren te weten te komen. Dit deed ik dan via de System.out.println functie. Na verloop van tijd bleek het echter beter om een logger te gebruiken om de gelogde data gemakkelijk te kunnen filteren en wegschrijven naar gewenste locaties. Hiervoor kon ik dan de log.info() functie van de Seam logger gebruiken. Een tweede probleem was een voorbeeld waarbij ik de lijsten die gemaakt werden volledig dynamisch wilde laten opvullen met een vast aantal rijen. Via pijltjes moest dan door de lijst kunnen gescrolled worden. Ik had hiervoor een stuk code gebruikt uit een vorig project van Java die perfect werkte. Helaas bleek een tijdje later dat er in Richfaces een component bestond waarmee ik met 1 lijntje op een veel betere manier en via AJAX mijn lijst dynamisch kon laten werken. Deze control is de rich:dataScroller geworden. Hieronder heb ik er een afbeelding van geplaatst. Een laatste voorbeeld was het vertalen van mijn applicatie. Ik had in het begin van mijn stage wel gezien dat de applicatie vertaalbaar moest zijn maar had hier geen rekening mee gehouden in de eerste weken van de implementatie. Hierdoor heb ik op het einde ook weer de meeste pagina’s moeten aanpassen om ze vertaalbaar te maken. Dit kon ik dan doen dankzij de messages.properties files en de Seam EL expressies messages[‘key’]. Natuurlijk zijn dit 3 zaken die ik nu dankzij de opgedane ervaring in de toekomst wel rekening mee zal houden en waar ik bij gevolg geen uren of dagen werk mee zal verliezen. Ik denk wel dat ik in het vervolg misschien beter alle vereisten van de applicatie vooraf goed doorneem en voor alle vereisten eerst een oplossing zoek alvorens ze effectief te gaan implementeren. Zo had ik misschien beter een klein stuk van de applicatie volledig op punt kunnen stellen om dan het overige deel van de applicatie op een goede manier aan te vullen. Ik had dan op dit kleine stuk misschien ook sneller feedback kunnen krijgen waardoor ik in de overgebleven tijd de applicatie zelf nog had kunnen verbeteren. In het begin van een project met technische analyse denk ik dat het dus beter is om deze analyse zo goed mogelijk uit te voeren aan de hand van de noden. De prioriteit mag dan dus niet bij de te maken applicatie liggen. Eindwerk Bram Gadeyne 2007-2008 123 9 Voor akkoord verklaard Frederik Dierickx Stagementor Hans De Neve Stagementor Sylvia Di Bono Stagegever Corneel Theben-Terville Stagebegeleider Eindwerk Bram Gadeyne 2007-2008 124 10 Literatuurlijst 10.1 Boeken • Beginning JBoss Seam o Autheur: Joseph Faisal Nusairat o Drukkerij: Apress o ISBN-10: 1-59059-792-3 • Practical Jboss Seam Projects o Autheur: Jim Farley o Drukkerij: Apress o ISBN-10: 1-59095-863-6 • Seam In Action (Covers Seam 2.0) o Autheur: Dan Allen o Unedited Draft 10.2 Webpagina’s • Demosite over Richfaces 3.2 o http://livedemo.exadel.com/richfaces-demo/index.jsp • Jira pagina’s van JBoss o http://jira.jboss.org • Het JBoss Forum o http://www.jboss.com/index.html?module=bb Eindwerk Bram Gadeyne 2007-2008 125 11 Bijlagen 11.1 Installatie onder Windows Eindwerk Bram Gadeyne 2007-2008 126 Installatie van Project Commas In Windows Eindwerk Bram Gadeyne 2007-2008 127 Inleiding In dit document bespreken we hoe we het project Commas kunnen gebruiksklaar maken. We zullen beginnen met het installeren en configureren van de verschillende servers. Daarna configureren we het project nog zodat deze aangepast wordt aan de omgeving. Downloaden van de benodigde software De laatste versie van de Java JDK Deze applicatie is geschreven in Java. Hierdoor hebben we dan ook de Java runtime environment (JRE) nodig om de applicatie uit te kunnen voeren. U kunt de laatste versie van JDK downloaden van de website van Sun ( http://java.sun.com) . Daar kunt u onder downloads kiezen voor downloads voor Java SE. Bij die downloads kies je dan voor de laatste JDK voor Windows. U kunt kiezen voor een offline installatie of een online installatie die dan de benodigde onderdelen voor u van het internet zal downloaden. JBOSS Server Onze applicatie wordt gehost vanaf een Applicatie Server. Wij kozen de JBOSS Server. Deze kunt u downloaden van http://labs.jboss.com/jbossas/downloads De huidige versie is versie 4.2.2 GA. U kunt het beste de gewone zip file downloaden. In onze geval jboss-4.2.2.GA.zip. Oracle Express Edition Op de achtergrond van onze applicatie draait een database. In ons geval de Oracle express edition. Deze kunt u downloaden van http://www.oracle.com/technology/software/products/database/xe/index.html Daar kiezen we voor de Windows versie. Let wel, u moet geregistreerd zijn op de website alvorens u de server kunt downloaden. Na het accepteren van de overeenkomst kunnen we de Oracle XE versie downloaden die we nodig hebben. We kiezen voor de “Western European” versie. Nu moeten we inloggen met onze gegevens van oracle.com of kunnen we een nieuw account aanmaken. Daarna kunt u de server downloaden. Oracle SQL Developer Om de database te kunnen installeren zullen we gebruik maken van deze software. U kunt het downloaden van http://www.oracle.com/technology/software/products/sql/index.html Voor deze download hebben we ook weer een oracle.com login nodig zoals bij het downloaden van Oracle Express. We kunnen hiervoor dezelfde login gegevens gebruiken. We kiezen de versie zonder JDK aangezien we de laatste versie van JDK al hebben gedownload. Eindwerk Bram Gadeyne 2007-2008 128 Installatie van de benodigde software Installatie van Java JDK Open de net gedownloade JDK installatie file. Accepteer de licentie overeenkomst Daarna ziet u welke onderdelen er standaard zullen geïnstalleerd worden. Ook kunt u kiezen om het installatie pad te veranderen. Wij laten het staan op de default waarden. Eindwerk Bram Gadeyne 2007-2008 129 Nu wordt Java geïnstalleerd op de computer die als server zal dienen. Nu krijgt u nog de mogelijkheid om een aantal onderdelen aan te passen aan uw behoeften. We laten echter alles standaard staan. Eindwerk Bram Gadeyne 2007-2008 130 Hierna is de installatie van Java afgelopen. Installatie van JBOSS Server We unzippen de gedownloade zipfile in C:\Program Files. Op die manier krijgen we daar een mapje “jboss-4.2.2.GA” waarin alle bestanden van onze server aanwezig zijn. Voordat we onze server kunnen starten moeten we nog de JAVA_HOME Variabele definiëren in onze systeemvariabelen. Daarvoor gaan we naar het configuratiescherm waar we kiezen voor Systeem. Op het tabblad geavanceerd kiezen we voor “Omgevingsvariabelen”. Eindwerk Bram Gadeyne 2007-2008 131 Eindwerk Bram Gadeyne 2007-2008 132 Door op nieuw te klikken kunnen we de JAVA_HOME variabele toevoegen. We laten deze nu verwijzen naar het installatie pad van onze JDK. Daarna klikken we over op "ok". We kunnen nu testen of onze installatie gelukt is. Dit kunnen we doen door in de bin map van de installatie map van de JBOSS Server het bestandje “run.bat” te openen. Nu zie je in een commando venster de server opstarten. Als we dit de eerste maal doen zal de firewall van Windows XP ons vragen of we Java SE willen blokkeren of niet. We kiezen hier voor Blokkering opheffen. Als alles goed verloopt, moet er op het einde iets te zien zijn zoals “16:33:28,890 INFO [Server] JBoss (MX MicroKernel) [4.2.2.GA (build: SVNTag=JBoss_4_2_2_GA date=200710221139)] Started in 19s:703ms” Eindwerk Bram Gadeyne 2007-2008 133 Sluit het commando venster niet! We kunnen nu surfen naar http://localhost:8080/web-console/. Als we dan volgende pagina te zien krijgen is de installatie gelukt. Installatie van Oracle XE Hiervoor hebben we de oracleXE.exe file nodig die we daarnet hebben gedownload. Eindwerk Bram Gadeyne 2007-2008 134 Tijdens de installatie van Oracle XE starten we ook de server van JBOSS op. Om te weten hoe dit moet zie het hoofdstuk “installatie van JBOSS Server”. We moeten dit doen omdat onze JBOSS server op poort 8080 werkt standaard. Onze Oracle XE heeft echter ook een webconsole die op dezelfde poort draait. Als deze poort tijdens de installatie niet in gebruik is kunnen we ook niet een andere poort voor deze console kiezen. Open het bestand oracleXE.exe Nadat we op volgende hebben geklikt, moeten we de licentie overeenkomst accepteren. We kunnen nu kiezen om Oracle op een andere da de standaard locatie te installeren. We laten dit staan en klikken op volgende. Eindwerk Bram Gadeyne 2007-2008 135 Omdat poort 8080 bezet is wordt ons gevraagd om een andere poort te kiezen voor de webconsole. Oracle stelt poort 8081 voor. U kunt deze waarde accepteren door op next te klikken. De standaard gebruiker in Oracle is de “SYSTEM” gebruiker. Oracle vraagt ons nu om een paswoord op te geven voor de SYSTEM gebruiker. Eindwerk Bram Gadeyne 2007-2008 136 Er wordt nog een overzichtje gegeven van de installatie die wordt gestart nadat we op install hebben geklikt. Na de installatie wordt ons gevraagd of we de database homepage willen openen. We zullen dit accepteren om een nieuwe gebruiker aan te kunnen maken. (via het menu start kan er eventueel later ook nog naar deze webpagina worden gegaan. Eindwerk Bram Gadeyne 2007-2008 137 We kunnen nu inloggen met de username SYSTEM en het paswoord die we daarnet hebben opgegeven tijdens de installatie. Op de volgende pagina kiezen we ervoor om een nieuwe gebruiker aan te maken zoals aangegeven in onderstaande afbeelding. Eindwerk Bram Gadeyne 2007-2008 138 We geven nu een gebruikersnaam en paswoord op voor onze nieuwe gebruiker. Wij kozen voor COMMAS als gebruikersnaam en paswoord als paswoord. Deze gebruiker is de gebruiker die we zullen gebruiken voor ons programma. Op die manier kan ons programma dan toegang krijgen tot de database. We kunnen deze gebruiker ook alle rechten geven op onze databank door alle vinkjes aan te vinken. Eindwerk Bram Gadeyne 2007-2008 139 U Kunt eventueel nog extra gebruikers aanmaken indien gewenst. Oracle SQL Developer installeren De installatie van Oracle SQL Developer bestaat enkel uit het unzippen van het zipbestand die we hebben gedownload. U kiest daarvoor een locatie zoals “C:\Program Files”. U kunt SQL Developer opstarten door sqldeveloper.exe uit te voeren die te vinden is in de unzipte map. De eerste maal dat we sqldeveloper opstarten wordt ons gevraagd naar de locatie van de java.exe file. Deze is te vinden in C:\Program Files\Java\jdk1.6.0_05\jre\bin\java.exe. Of in de jre/bin map van de Java installatie folder als u deze op een andere locatie zou geïnstalleerd hebben. Eindwerk Bram Gadeyne 2007-2008 140 Daarna wordt ons gevraagd om settings van een vorige versie te migreren maar omdat dit een nieuwe installatie is kiezen we dus voor “No”. Door rechts te klikken op Connection en te kiezen voor new connection kunnen we nu een nieuwe connectie aanmaken. Nu moeten we inloggen met ons COMMAS account. Deze gebruiker beschikt over de rechten op de Commas databank. Eindwerk Bram Gadeyne 2007-2008 141 Door op test te klikken kunnen we ook onmiddellijk al testen of onze gegeven correct zijn. Daarna klikken we op connect. We zien nu dat er nog geen tabellen zijn aangemaakt in de COMMAS databank. Hiervoor kunnen we het script export.sql uitvoeren. Via het menu File-> Open kunnen we de locatie van het script aantonen. Daarna kunnen we het laten uitvoeren door op de knop script uitvoeren te klikken. Er wordt ons dan gevraagd via welke connectie we het script willen laten uitvoeren. We kiezen daarvoor onze Oracle local connectie. Eindwerk Bram Gadeyne 2007-2008 142 Als we nu recht klikken op tables en kiezen voor refresh dan zouden we daar onze 21 tabellen moeten zien verschijnen. We kunnen ook refresh kiezen bij sequences en daar zouden 20 sequences te vinden moeten zijn. Configuratie server JNDI connectie Onze Application Server (JBOSS Server) moet kunnen communiceren met onze database (Oracle). Daarvoor moeten we een JNDI connectie voorzien. Deze moet een unieke naam hebben die ook binnen ons project gekend is. Bij ons is dit “jdbc/OracleDS”. Het bestand oracle-ds.xml bevat de configuratie voor onze Oracle connectie. Eventueel kunt u de username en het paswoord nog aanpassen indien u tijdens de installatie een andere zou gebruikt hebben. Eindwerk Bram Gadeyne 2007-2008 143 Dit bestand plaatsen we dan in de map “C:\Program Files\jboss-4.2.2.GA\server\default\deploy”. Of in de server\default\deploy map indien u een andere installatie locatie zou gekozen hebben. We plaatsen ook het bestand ojdbc14_g.jar in de \server\default\lib. Op die manier beschikt onze server over een Driver om connectie te kunnen maken met de Oracle Database. Deployment van het project Één van de laatste zaken die moeten gebeuren is het uiteindelijke project op de server plaatsen. Dit doen we door de “ProjectCommas-ear.ear” map in onze deploy map te zetten. Dit is dezelfde locatie als waar we de databank connectie hebben geplaatst. In ons geval dus “C:\Program Files\jboss-4.2.2.GA\server\default\deploy”. Option.Properties In de WEB-INF\classes map van onze war file vinden we het bestand option.properties. Hierin kunnen we enkele opties veranderen die de werking van onze applicatie kunnen beïnvloeden. De opties.properties file wordt automatisch om de minuut ingelezen door onze webserver. Op die manier kunnen we opties veranderen zonder de webserver te moeten opnieuw opstarten. Directory’s In deze directory’s worden bestanden opgeslaan soms tijdelijk, soms permanent. De locatie hiervan kan dus worden gewijzigd. • • • • Mail rapportendir=C:/Program Files/commas/rapporten/ pdfdir=C:/Program Files/commas/pdf klantentevredenheidfilesdir=C\:/Program Files/commas/files/Klantentevredenheid/ certificatenfilesdir=C\:/Program Files/commas/files/Certificaat/ Deze 2 opties bepalen de locatie van de smpt mailserver van onze applicatie alsook de frequentie waarop automatisch op te verzenden mails moet worden gecontroleerd. mailserver=HUSEXV02.dolmen.be mailtimertask=60000 Varia: Als laatste hebben we ook nog enkele opties die gebruikt worden om de werking van ons programma te veranderen. Listsize geeft de lengte van de weergegeven lijsten terug. nrOfPages geeft weer hoeveel pagina’s er moeten worden weergegeven door de datascrollers. Defaultpass is de instelling van het paswoord die standaard wordt gebruikt bij het aanmaken van een nieuwe medewerker. Timertaks is de instelling in milliseconden van om de hoeveel tijd de options.properties file moet worden ingelezen. Eindwerk Bram Gadeyne 2007-2008 144 Opgelet! De timertask optie zal enkel veranderingen teweeg brengen bij het opnieuw opstarten van de server. • • • • listsize=5 defaultpass=paswoord timertask=60000 nrOfPages=5 Commas map In de Program Files map op de C-schijf plaatsen we de map “commas” waarin een aantal belangrijke mappen zitten voor ons project voor fileupload. Project testen We controleren in de commas map het bestand options.properties of alle waarden wel correct zijn ingegeven. Daarna beginnen we met het opstarten van de server (zie installatie JBOSS Server voor meer uitleg). Als alles goed verloopt dan kunnen we nu surfen naar http://localhost:8080/ProjectCommas/ . Je kan er inloggen met de gebruikersnaam “administrator” en het paswoord “paswoord”. Eindwerk Bram Gadeyne 2007-2008 145 11.2 Installatie onder Linux Eindwerk Bram Gadeyne 2007-2008 146 Installatie van Project Commas onder Linux Eindwerk Bram Gadeyne 2007-2008 147 Inleiding In dit document bespreken we hoe we het project Commas kunnen gebruiksklaar maken onder linux. We zullen beginnen met het installeren en configureren van de verschillende servers. Daarna configureren we het project nog zodat deze aangepast wordt aan de omgeving. Downloaden van de benodigde software De laatste versie van de Java JDK Deze applicatie is geschreven in Java. Hierdoor hebben we dan ook de Java runtime environment (JRE) nodig om de applicatie uit te kunnen voeren. U kunt de laatste versie van JDK downloaden van de website van Sun ( http://java.sun.com) . Daar kunt u onder downloads kiezen voor downloads voor Java SE. Bij die downloads kies je dan voor de laatste JDK voor linux. U kunt kiezen voor een offline installatie of een online installatie die dan de benodigde onderdelen voor u van het internet zal downloaden. In Ubuntu Linux kunnen we echter deze installatie ook automatisch laten gebeuren. Dit doen we door in Synaptic pakketbeheer te kiezen voor jdk 6 (of de laatste versie van de jdk). Eindwerk Bram Gadeyne 2007-2008 148 JBOSS Server Onze applicatie wordt gehost vanaf een Applicatie Server. Wij kozen de JBOSS Server. Deze kunt u downloaden van http://labs.jboss.com/jbossas/downloads De huidige versie is versie 4.2.2 GA. U kunt het beste de gewone zip file downloaden. In onze geval jboss-4.2.2.GA.zip. Oracle Express Edition Op de achtergrond van onze applicatie draait een database. In ons geval de Oracle express edition. Deze kunt u downloaden van: http://www.oracle.com/technology/software/products/database/xe/index.html Daar kiezen we voor de linux versie. Let wel, u moet geregistreerd zijn op de website alvorens u de server kunt downloaden. Na het accepteren van de overeenkomst kunnen we de Oracle XE versie downloaden die we nodig hebben. We kiezen voor de “Western European” versie. Nu moeten we inloggen met onze gegevens van oracle.com of kunnen we een nieuw account aanmaken. Daarna kunt u de server downloaden. Oracle SQL Developer Om de database te kunnen installeren zullen we gebruik maken van deze software.U kunt het downloaden van http://www.oracle.com/technology/software/products/sql/index.html Voor deze download hebben we ook weer een oracle.com login nodig zoals bij het downloaden van Oracle Express. We kunnen hiervoor dezelfde login gegevens gebruiken. We kiezen de versie zonder JDK aangezien we de laatste versie van JDK al hebben gedownload. Installatie van de benodigde software. Installatie van de JDK 1.6 Om JDK te installeren onder een andere distributie van Linux kunt u installatie instructies vinden op de site van SUN of op de site van uw distributie. In Ubuntu Linux kunnen we deze installatie automatisch laten gebeuren. Dit doen we door in Synaptic pakketbeheer te kiezen voor jdk 6 (of de laatste versie van de jdk). Eindwerk Bram Gadeyne 2007-2008 149 Installatie van JBOSS Server We unzippen de gedownloade zipfile ergens op de linux computer. Bijvoorbeeld /home/bram/Bureaublad. Op die manier krijgen we daar een mapje “jboss-4.2.2.GA” waarin alle bestanden van onze server aanwezig zijn. Voordat we onze server kunnen starten moeten we nog de JAVA_HOME Variabele definiëren in onze systeemvariabelen. In Ubuntu Linux werd voor ons de JAVA_HOME variabele al geconfigureerd. Om te weten hoe dit moet voor uw distributie kunt u op de site van Sun raadplegen of de site van uw distributie. oracle-xe installatie We openen het gedownloade *.deb bestand die de installatie bestanden van onze oracle XE server bevat. Daarna krijgen we volgend scherm te zien. Eindwerk Bram Gadeyne 2007-2008 150 We klikken op pakket installeren en alle benodigde libraries worden voor ons gedownload en geïnstalleerd. Let wel dat je hiervoor best een actieve internet connectie hebt. Eindwerk Bram Gadeyne 2007-2008 151 Na de installatie voeren we zoals aangegeven het commando sudo /etc/init.d/oracle-xe configure uit in de terminal. Eindwerk Bram Gadeyne 2007-2008 152 Nu kunnen we surfen naar http://127.0.0.1:9090/apex om onze server verder te configureren. Indien dit niet onmiddellijk werkt kunnen we ook het commando sudo /etc/init.d/oracle-xe forcereload uitvoeren. Toevoegen van een gebruiker aan de dba groep Om de Oracle server te kunnen laten werken moeten we eerst nog onze gebruiker toevoegen aan de rol “dba.” zoals hieronder staat aangegeven. Na het toevoegen moeten we onze huidige gebruiker even uitloggen uit het systeem en vervolgens opnieuw aanmelden. Daarna kunnen we onze server herstarten met het commando sudo /etc/init.d/oracle-xe forcereload. Eindwerk Bram Gadeyne 2007-2008 153 Toevoegen van een gebruiker aan de Oracle server Eindwerk Bram Gadeyne 2007-2008 154 Nadat we zijn ingelogd met de gebruikersnaar SYSTEM en het tijdens de configuratie opgegeven paswoord, kunnen we een nieuwe gebruiker toevoegen die we COMMAS zullen noemen. Eindwerk Bram Gadeyne 2007-2008 155 Installatie SQL Developer Omdat wij in Ubuntu met een op debian gebaseerd systeem zitten moeten we de door Oracle gedistribueerde .rpm file omzetten naar een .deb file. Dit kunnen we doen met het commando alien –script bestandsnaam. Daarna kunnen we de .deb file gewoon openen en installeren door op pakket installeren te klikken. Eindwerk Bram Gadeyne 2007-2008 156 Configuratie applicatie Configuratie database via sql developer De eerste keer dat we onze sql developer opstarten (te vinden bij de geïnstalleerde toepassingen) wordt ons gevraagd of we de settings van een vorige installatie willen overnemen. We kiezen voor “no”. Nadat we in het systeem zijn ingelogd moeten we een nieuwe connectie toevoegen die we “local” noemen. Eindwerk Bram Gadeyne 2007-2008 157 We kunnen onze connectie testen door op de knop test te klikken. Daarna klikken we op de knop connect. Nu openen we het bestand export.sql (of export-data.sql om test data mee te installeren). Eindwerk Bram Gadeyne 2007-2008 158 Vervolgens klikken we op het 2de groene pijltje om het script uit te voeren. Daarna wordt ons gevraagd via welke connectie we het script willen uitvoeren. We kiezen onze net aangemaakte “local” connectie. Controleer of alle tabellen zijn aangemaakt. Indien dat niet zo is kunt u het script nogmaals proberen uit te voeren. Installatie EAR Eindwerk Bram Gadeyne 2007-2008 159 Plaats de ear file in de deploy locatie samen met het configuratiebestand oracle-ds.xml. Controleer in het configuratie bestand de juistheid van de connectie gegevens. Voeg in de map \server\default\lib het bestand ojdbc14_g.jar. Op die manier beschikt de server over een driver om te kunnen verbinden met de Oracle Database. Configuratie EAR In ons EAR bestand bevindt zich het bestand ProjectCommas.war. In deze war bevindt zich op de locatie /WEB-INF/classes het bestand options.properties. In deze file kunt u enkele opties veranderen die de werking van onze applicatie veranderen. Controleer hier zeker de correctheid van de 4 directories die aangeven waar respectievelijk de rapporten lokaliseren, de pdf's opslaan en de 2 mappen waarin klantentevredenheidsbestanden en certificaatbestanden worden opgeslagen. Zorg ervoor dat de wijzigingen opgeslagen worden in de EAR file. Configuratie Mail Onze applicatie is in staat om mails te verzenden. De connectie hiervoor wordt geconfigureerd in het bestand components.xml die zich in de map WEB-INF van de war file bevindt. In dit bestand kunt u de regel <mail:mail-session host="HUSEXV02.dolmen.be"/> aanpassen en een andere host instellen. Zorg ervoor dat de wijzigingen opgeslagen worden in de EAR file. Opstarten applicatie Opstarten Jboss Server In de map waar we onze Jboss server hebben uitgepakt gaan we met onze terminal naar de map bin. In deze map bevindt zich het bestand run.sh. Dit kunnen we uitvoeren door “./run.sh” uit te voeren. We zien vervolgens de server opstarten. Eindwerk Bram Gadeyne 2007-2008 160 Opstarten browser Na de installatie kunnen we surfen naar de url http://localhost:8080/ProjectCommas. Daarna wordt onze applicatie opgestart. Voor het inloggen, kunt u standaard aanmelden met de gebruiker “administrator” en het paswoord “paswoord”. Eindwerk Bram Gadeyne 2007-2008 161 11.3 Actierapport Dit is een rapport die kan gegenereerd worden met JasperReports. Het geeft een overzicht van alle Acties van de medewerker dummy1. Eindwerk Bram Gadeyne 2007-2008 162 Eindwerk Bram Gadeyne 2007-2008 163 11.4 Functiebeschrijving rapport In dit rapport wordt een samenvatting van een functiebeschrijving weergegeven. Recursief worden alle competenties op het rapport ingevuld. Dit is mogelijk via de subrapporten. Eindwerk Bram Gadeyne 2007-2008 164 Eindwerk Bram Gadeyne 2007-2008 165 Eindwerk Bram Gadeyne 2007-2008 166