StudentApp klaar voor nu

Hallo wereld!

Ik heb nog een aantal laatste aanpassingen gemaakt aan het studenten datasysteem. Dit zullen waarschijnlijk de laatste aanpassingen zijn die ik voorlopig zal maken. In plaats daarvan ga ik verder met nieuwe projecten, waarvan ik al wat gezegd had in mijn mededeling van vorige week.

Ten eerste heb ik de code een beetje gereorganiseerd. In JavaFX maakt men gebruik van wat men noemt Scenes om de windows te vullen met alle interface componenten. Tot nu toe had ik al deze Scenes in een method gepropt. Het resultaat? Een lange onoverzichtelijke rij van code met allerlei interface componenten die allemaal naamconflicten oproepen die constant moeten worden opgelost. Nu heb ik elke Scene laten genereren in een aparte method per stuk. Het resultaat? Een lange onoverzichtelijke rij van methods die in ieder geval geen naamconflicten meer veroorzaken. Na al het scrollen en programmeren en tijdens het schrijven van dit bericht kwam ik er echter weer achter dat je die lange onoverzichtelijke rijen code in Netbeans ook kon inklappen door op het minteken ernaast te klikken. Zucht…

Bovendien bleek het ook handig te zijn om Scenes te laten genereren in de functionaliteit van andere Scenes, door die methodes op deze plekken in te voeren. Bijvoorbeeld om de naam van de ingelogde student aan te passen tijdens het inloggen zelf. Waarschijnlijk kan het nog steeds allemaal veel beter, maar JavaFX was nog steeds onwennig voor mij en dit is de beste oplossing die ik voor nu kon vinden.

Ook heb ik de mogelijkheid om de save folder te wijzigen toegevoegd. Zoals ik al zei is dat veel professioneler. Niet alleen kun je hem nu wijzigen, het is nu ook niet meer zo dat hij automatisch wordt gemaakt in je C directory. In plaats daarvan wordt automatisch de folder geselecteerd waarin je de jar-file hebt opgeslagen voor opslag. Wees echter gewaarschuwd, als je hem in je IDE runt dan wordt automatisch de build folder geselecteerd, en die is niet geschikt voor permanente opslag. Zorg er dan in dit geval dus voor dat je de folder dan ook wijzigt met de handige functionaliteit die ik heb toegevoegd! Wil je niet dat de informatie direct in je geselecteerde folder wordt opgeslagen maar een nieuwe folder aanmaken? Dat kan ook. Type gewoon de naam van de folder die je wilt maken achter het bestandspad en de folder wordt automatisch aangemaakt.

Daarnaast heb ik ook een simpele zoekfunctie toegevoegd. Niets bijzonders, maar wat heb je aan een database waarin je niet kan zoeken? In mijn database staan dan misschien maar slechts een paar elementen, maar in een echte toepassing zouden er al snel honderden tot duizenden rijen in staan. De droom dat deze database een echte toepassing zou worden heb ik voorlopig echter even uitgesteld. Voor nu is het dan ook alleen maar mogelijk om op ID-nummer te zoeken. Meer als proof-of-concept dan als handige functionaliteit dus.

Tot slot heb ik ook een simpele cirkeldiagram scene toegevoegd die de verdeling van de studenten over de verschillende studiejaren toont. Om deze functioneel te maken heb ik dan de beschikbare jaarkeuzes beperkt tot 1 tot en met 5. Deze scene is mijn poging om een beetje data analyse aan het data opslag systeem toe te voegen. Want data analyse is natuurlijk veel leuker dan data opslag!

En dat is het! De code is te vinden op https://github.com/SamsonCodes/StudentenData/tree/evenmorechanges. Het is tijd voor een nieuw project. Wat voor project? Nou, dat vertel ik jullie volgende week natuurlijk.

Tot de volgende keer!

 

Java Tutorial: Data laden

Update: Dankzij Thom, een oud-medestudent en vriend van mij, is deze tutorial nu verbeterd. Thom, je bent een held!

Gegroet Dataridders,

Welkom bij de tweede Java data tutorial. Dit keer zal ik jullie leren hoe je data die je hebt opgeslagen in een bestand als tekst kunt laden. Opnieuw geldt hierbij: Dit is hoe ik het altijd gedaan heb en niet per se de enige noch de beste methode. Voor deze tutorial gelden dezelfde benodigdheden als bij de vorige:

  • Java SDK geïnstalleerd op je systeem
  • Een Java IDE, bijvoorbeeld Netbeans of Eclipse
  • Basiskennis van programmeren met Java

Om te beginnen zullen we weer eerst onze methode definiëren. We willen een functie die als input een bestandslocatie filePath voor een tekstbestand neemt en dan als output ons de tekst in dat bestand geeft in een ArrayList van String gegevens. En net zoals de vorige keer mag de functie weer static zijn, aangezien er geen object nodig is om hem te gebruiken. Dit ziet er dan als volgt uit:

public static ArrayList<String> loadData(String filePath)
{
ArrayList<String> loadedData = new ArrayList();
return loadedData;
}

Op dit moment wordt er nog niets geladen en is de ArrayList die wordt gereturned door onze methode nog leeg. Laten we daar verandering in brengen. Om onze data te laden zullen we gebruik maken van een FileReader. Moet ik echt uitleggen wat deze class doet?

Hij leest bestanden.

Maar een FileReader is niet erg efficiënt voor onze toepassing. Daarom hebben we nog een class nodig: BufferedReader. Een BufferedReader neemt als input een ander Reader object, en het resultaat is een Reader met byte-buffering, welke efficiënter is.

Echter, voor onze toepassing maakt die extra efficiëntie niet veel uit. We zijn meer geïnteresseerd in de readLine() methode van de BufferedReader, maar daarover later meer. Dat ziet er dan als volgt uit:

FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);

Wat in Google’s naam is byte-buffering?! Eerlijk gezegd heb ik geen idee. Sterker nog, voordat ik deze tutorial maakte wist ik niet eens wat een BufferedReader was, waarom ik het moest gebruiken en waarom het een FileReader als input nam. Maar ik wist wat Google was en ik wist wat copy-paste was en dus ik wist hoe ik data moest laden.

Ik wilde voor deze tutorial echter toch wel iets meer kunnen uit leggen over het onderliggende proces dan dat, en dus heb ik maar wat onderzoek gedaan. Wil je meer weten over byte-buffering dan heb je twee opties: Wacht totdat ik besluit een tutorial of blog post te doen over byte-buffering, of doe wat ik doe als ik iets niet weet: Google het!

Genoeg intermezzo, verder met programmeren!

Net zoals bij de constructor van de PrintWriter moeten er weer wat Exceptions opgevangen worden bij de initialisatie van de FileReader. We zullen de code dus weer met try en catch omringen.

try
{
fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
}
catch (FileNotFoundException ex)
{
Logger.getLogger(DataLoadingTutorial.class.getName()).log(Level.SEVERE, null, ex);
}

Nu kunnen we de BufferedReader gebruiken om ons bestand te lezen. We doen dat met de eerder genoemde readLine() functie van BufferedReader en een while loop. De readline() functie stelt ons in staat hele regels tegelijk te lezen in ons programma, iets wat met FileReader niet kan. Zolang ons bestand nieuwe regels met tekst bevat zal readLine() ons deze geven. We willen voor onze while loop dan de output van readLine() toe blijven voegen aan onze ArrayList totdat readLine() ons een lege regel geeft. Dit ziet er dan als volgt uit:

String line;
while ((line = bufferedReader.readLine()) != null)
{
loadedData.add(line);
}

Ook readLine genereert echter weer wat vervelende Exceptions die moeten afgehandeld worden, IOExceptions dit keer. We zullen dus een catch-clausule moeten toevoegen:

catch (FileNotFoundException ex)
{
Logger.getLogger(DataLoadingTutorial.class.getName()).log(Level.SEVERE, null, ex);
}
catch (IOException ex)
{
Logger.getLogger(DataLoadingTutorial.class.getName()).log(Level.SEVERE, null, ex);
}

De Logger code is overigens weer automatisch gegenereerd en wordt gebruikt om de foutmeldingen in het log scherm te weergeven maar is niet essentieel, en kan weggelaten of bijvoorbeeld vervangen worden door een “System.out.println()” met tekst naar keuze.

In principe werkt deze code zo dan ook, maar dankzij Thom weten we nu hoe het beter kan. Ten eerste was ik vergeten om de reader te sluiten nadat de File gelezen was. De meest elegante methode om dit te doen met Java is door de constructor te verplaatsen naar de try opening zoals hieronder:

try (BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath)))
{
String line;
while ((line = bufferedReader.readLine()) != null)
{
loadedData.add(line);
}
}

Dit zorgt ervoor dat de reader gesloten wordt, zelfs als er een Exception plaatsvindt. Hetzelfde principe geldt overigens voor de PrintWriter van de savefunctie.

try (PrintWriter writer = new PrintWriter(filePath, StandardCharsets.UTF_8.name()))

Daarnaast is een FileNotFoundException een subclass van een IOException en kunnen we de catch voor de FileNotFoundException dus weglaten, en alles met de IOException opvangen.

catch (IOException ex)
{
Logger.getLogger(DataLoadingTutorial.class.getName()).log(Level.SEVERE, null, ex);
}

Tot slot is er blijkbaar nog een alternatieve, makkelijkere manier om gegevens te laden met Java 8, door gebruik te maken van Streams met de Files class.

// Alternative: Java 8 way with Streams
try
{
System.out.println(“”);
System.out.println(“Inhoud:”);
Files.lines(Paths.get(PATH + “test.txt”)).forEach(System.out::println);
}
catch (IOException ex)
{
Logger.getLogger(DataLoadingTutorial.class.getName()).log(Level.SEVERE, null, ex);
}

Ja, ik weet het, waarom niet gewoon deze tutorial daarmee beginnen?! Maar ik zei al, ik ging jullie laten zien hoe IK het deed, en ik kende deze manier nog niet. Bovendien kan ik jullie er op het moment ook weinig over deze alternatieve methode uitleggen, en denk ik dat het proces dat ik heb uitgestippeld in mijn methode nog steeds heel leerzaam is. In de toekomst zal ik deze manier echter misschien ook gaan gebruiken.

En klaar is kees!

Zolang je nu maar de juiste bestandslocatie opgeeft zal deze code alle regels uit je tekstbestand in een ArrayList zetten. De volledige code, inclusief extra code voor het testen is te vinden op https://github.com/SamsonCodes/DataLoadingTutorial. Trouwens, mocht je het nog niet weten, de Java files binnen een Netbeans project zijn te vinden in de src folder. In dit geval is er slechts een Java file, en die is te vinden in de dataloadingtutorial folder (in Netbeans: package) binnen deze src folder.

Dat is alles voor nu,

 

Tot de volgende keer!

Java Tutorial: Data opslaan

Hallo wereld!

Dit keer heb ik een tutorial voor jullie gemaakt over het opslaan van data met Java.

Er zijn meerdere manieren om dit te doen, en ze zijn niet per se allemaal even goed, en sommige manieren zijn beter in bepaalde situaties dan in andere. Maar ik ga jullie leren hoe IK het tot nu toe heb gedaan voor MIJN projecten. Als jij dit leest en jij denkt een betere manier te weten, laat het me weten! Ik wil het graag horen.

Om deze tutorial te volgen heb je nodig:

  • Java SDK geïnstalleerd op je systeem
  • Een Java IDE, bijvoorbeeld Netbeans of Eclipse
  • Basiskennis van programmeren met Java

Met dat uit de weg, laten we beginnen. Eerst zullen we het frame van onze methode ontwerpen. We willen een methode maken die als input een ArrayList van String gegevens data neemt om op te slaan en een String met de opslaglocatie filePath. De methode heeft geen output, maar schrijft de data naar een tekstbestand in de opgeven locatie. Als het tekstbestand nog niet bestaat dan wordt het overigens gecreëerd, maar de folder moet wel al bestaan. Dit ziet er dan als volgt uit:

public static void saveData(ArrayList<String> data, String filePath) { }

We kunnen de methode de static eigenschap geven omdat het niet nodig is om een object te initialiseren om hem te gebruiken, de methode is zelfstandig. Public is hier ook wel handig zodat je hem overal in je project kan gebruiken.

Om data op te slaan in een tekstbestand zullen we gebruiken van de PrintWriter class. Deze class stelt je in staat om tekst te printen in een “tekst outputstream”. Om de PrintWriter te initialiseren gebruiken we de volgende code:

PrintWriter writer = new PrintWriter(filePath, “UTF-8”);

De “UTF-8” String geeft informatie over de karakters die gebruikt kunnen worden in het tekst bestand. Maar maak je daar maar niet al te druk om.

Er is echter nog een probleem met de bovenstaande code. Als je de informatie op docs.oracle.com doorleest zul je namelijk zien dat deze constructor een aantal Exceptions gooit die moeten worden opgevangen. Daarom zullen we de code omringen met een try catch statement. Als je Netbeans gebruikt dan kun je deze automatisch laten genereren door de regel te selecteren, op Alt-Enter te drukken en dan te selecteren “Surround Statement with try catch”. Vervolgens kunnen we eventueel Alt-Enter opnieuw gebruiken om er een multicatch van te maken, zodat alle foutmeldingen in een catch statement worden gevangen.

Het resultaat is het onderstaande. Eventueel kun je deze regels gewoon overtypen of kopiëren uit de volledige code.

try
{
PrintWriter writer = new PrintWriter(filePath, “UTF-8”);
}
catch (FileNotFoundException | UnsupportedEncodingException ex)
{
Logger.getLogger(DataHandlingTutorial.class.getName()).log(Level.SEVERE, null, ex);
}

De Logger code is hier dus automatisch gegenereerd en wordt gebruikt om de foutmeldingen in het log scherm te weergeven maar is niet essentieel, en kan weggelaten of bijvoorbeeld vervangen worden door een “System.out.println()” met tekst naar keuze.

Nu dat we de PrintWriter hebben geïnitialiseerd kunnen we beginnen met het opslaan van de gegevens. Om dit te doen gebruiken we een simpele for loop om alle data te printen.

for(String line: data)
{
writer.println(line);
}

Tot slot sluiten we nu we klaar zijn de PrintWriter met de volgende regel:

writer.close();

En klaar is kees! De volledige code kun je vinden op https://github.com/SamsonCodes/DataSavingTutorial. Wees geadviseerd dat de code niet voor je zal werken tenzij je de opslaglocatie PATH aanpast.

Maar als je kijkt naar de code die ik bijvoorbeeld heb gebruikt in mijn studenten datasysteem zul je zien dat er een klein verschil is. De loop voor het schrijven naar het bestand is daar anders:

data.stream().forEach((line)
->
{
writer.println(line);
});

Dit is te danken aan Netbeans. Die gaf mij namelijk de suggestie om een Functional Operator te gebruiken. Wat dat was wist ik niet, maar als Netbeans het beter vondt, waarom niet? Dus liet ik Netbeans het aanpassen en het werkte nog steeds precies hetzelfde.

Maar om niet al te onprofessioneel over te komen heb ik dan maar besloten het eens te googelen voor deze tutorial. Het antwoord op wat een Functional Operator nou is wordt hier gegeven op StackExchange. Het komt er in principe op neer dat het korter en beter te lezen is in het geval dat je nested loops gebruikt of meerdere loops die gedeeltelijke bewerkingen doen. Weer wat geleerd!

Dat is alles voor nu.

Tot de volgende keer!

StudentApp ontwikkelt zich verder

Hallo wereld!

Opnieuw een vooruitgangsrapport over het studenten data systeem, of StudentApp. Kort voor applicatie, niet te verwarren met de Android variant.

Inmiddels is het programma een stuk gevorderd sinds de vorige post. Een van de belangrijkste aanvullingen is die van een save systeem. Want, wat heb je aan een database die elke keer als je hem sluit alles vergeet wat je hebt gedaan?

Vrij weinig.

De informatie wordt opgeslagen in een map in C:\StudentenDataManager. Natuurlijk is dit niet de meest professionele oplossing en zou het beter zijn als de gebruiker zelf een map kan aanwijzen, maar voor nu werkt dit prima. De gegevens worden opgeslagen in een zelf bedacht XML-format en kunnen vervolgens door de code weer gebruikt worden om de objecten opnieuw aan te maken.

studenten data in XML-format

Ook wordt er nu bij het inloggen gekeken naar het wachtwoord. Voor nu laat ik dit wachtwoord echter standaard ingevuld zijn bij het opstarten zodat ik het niet steeds opnieuw hoef te typen. Het is voor nu dan ook voor elke gebruiker hetzelfde. Wat is het wachtwoord? Het wachtwoord is “dataridder” natuurlijk, wat anders?

Hoe kun je dit wachtwoord nou niet goed krijgen?

De studenten kunnen nu dan dus ook inloggen op hun persoonlijke account via hun studentennummer en zich in- en uitschrijven voor vakken. Ook kan de administrator nu studenten verwijderen in plaats van alleen toevoegen en zijn er meer gegevens om in te vullen. De studentengegevens en de inschrijfgegevens worden nu ook weergegeven in een TableView. Een JavaFX component dat gegevens presenteert in een tabel. Had je nooit geraden, of wel?

Schrijf je in voor plezier!
Voeg al je vrienden toe aan het systeem!

TableView was iets complexer dan de andere interface componenten van JavaFX om te leren gebruiken. Er is een enorme hoeveelheid aan opties en er is makkelijk een klein boek vol aan uitleg en documentatie over te vinden. Tegelijkertijd is het echter ook niet al te moeilijk om uit te vogelen zo lang je je maar richt op de informatie die je nodig hebt om te beginnen en je niet laat afschrikken of afleiden door de rest. Dat is een algemeen advies, maar wat TableView betreft, zorg eerst dat je een tabel op je interface hebt zonder je druk te maken over functionaliteit en maak dan een ObservableList van de gegevens waar je hem mee wilt vullen. ObservableList klinkt ingewikkeld maar is in principe niets anders dan een ArrayList voor in een tabel. Zorg ervoor dat de kolommen de juiste data presenteren en vergeet niet om alle data daadwerkelijk zowel aan de ObservableList toe te voegen als de list aan de tabel toe te voegen. En klaar is kees!

Dat zijn de belangrijkste aanvullingen tot nu toe. De code is te vinden op https://github.com/SamsonCodes/StudentenData/tree/morechanges. Dat is alles voor nu.

Tot de volgende keer!

Vooruitgangsrapport Studenten Datasysteem

Gegroet Dataridders,

Ik ben inmiddels begonnen aan het programmeren van mijn studenten datasysteem. En hoewel ik nog niet al te ver ben gekomen is de eerste opzet er al wel.

Het was lastiger dan ik van te voren had gedacht om met JavaFX te werken. Ik was veel tijd kwijt aan het zoeken naar een opzet met de interface en een soort game-loop in afzonderlijke threads. Ik had eerst dan ook deze loop in de main thread en wilde de JavaFX applicatie in een afzonderlijke class en thread doen maar dat gaf een hoop foutmeldingen die ik niet wist op te lossen. Dus heb ik het uiteindelijk maar omgedraaid en heb ik de JavaFX applicatie als main class genomen en ben ik van plan geen game-loop meer te gebruiken, maar alle achtergrond activiteit te laten activeren als respons op de user input.

Tot nu toe heb ik een simpel inlogscherm, een invoerscherm voor het invoeren van studenten en een titelscherm voor het aanmelden voor vakken voor studenten. Voor nu wordt bij het inlogscherm alleen de naam als input gecontroleerd. De naam Admin laat je inloggen in het invoerscherm, en een ‘s’ gevolgd door het id nummer, bijvoorbeeld s10000 (het eerste nummer dat gebruikt wordt), laat je als student inloggen mits je in het systeem staat. In beide schermen kun je ook uitloggen en terug naar het inlogscherm gaan. Hieronder zijn wat screenshots van de applicatie zoals hij er nu uitziet. Zie https://github.com/SamsonCodes/StudentenData voor de code.

Inlogscherm

Log in als admin
Ingelogd als admin
Student toegevoegd
Log in als student s10000
Ingelogd als student

Dat is alles voor nu. Tot de volgende keer!

Project Aankondiging: Studenten Datasysteem

Gegroet Dataridders,

Kort geleden ben ik een gratis cursus begonnen op Udemy: Practice Java by Building Projects. Een van de opdrachten in deze cursus betreft het maken van een Studenten Datamanagement Systeem.

Nu zijn de eisen bij deze opdracht vrij laagdrempelig. Het de bedoeling om een applicatie in Java te schrijven die het mogelijk maakt om via de console studentendata in te voeren, aldus voor een fictieve beheerder, en daarnaast om studenten in staat te stellen om zich in te schrijven voor vakken. Elk object binnen deze applicatie heeft slechts een paar variabelen en functies nodig, en ik had de applicatie dan ook binnen een uurtje geschreven. De code is te vinden op https://github.com/SamsonCodes/Business-Applications

Wat dat betreft was deze cursus dus een beetje een anticlimax tot dusver, hoewel het qua kwaliteit wel prima in orde is en een goed beginpunt is voor beginners. Maar later kreeg ik het idee om deze en de andere opdrachten in deze cursus tot een nieuw niveau te brengen en applicaties te schrijven die de praktijk dichter benaderen. Applicaties met een daadwerkelijke user-interface, in plaats van de console, en met wachtwoord beveiliging, meer en meer realistische variabelen etc. En dit idee heeft dan ook mede bij gedragen aan de keuze voor het beginnen van een blog over datasystemen.

Om te beginnen zal ik dit dus doen voor het studenten datasysteem. In tegenstelling tot de code op Github zal ik dit waarschijnlijk gaan doen in Netbeans in plaats van Eclipse. Ik heb namelijk de meeste ervaring met Netbeans en heb voor deze projecten alleen Eclipse gebruikt om er wat meer ervaring mee op te doen, voor het geval dat ik er ooit weer eens mee moet werken. Maar ik vindt Netbeans persoonlijk veel fijner om in te werken.

Ter voorbereiding op dit project ben ik ook al begonnen met experimenteren met de JavaFX bibliotheek en heb ik een tutorial gevolgd op docs.oracle.com. In deze tutorial heb ik geleerd om een simpel inlogscherm te maken en hoe hem te exporteren naar bruikbare applicaties, alhoewel ik voor dat laatste nog wat extra onderzoek zal moeten doen. Hoe dan ook, ik heb besloten om deze applicatie te gaan maken met JavaFX aangezien de consensus online leek te zijn dat deze bibliotheek de toekomst is en de Swing bibliotheek (mijn go-to tot dusver) het verleden. Bovendien was mijn eerste indruk van JavaFX ook vrij positief, het is simpel genoeg om te leren en de opties voor stijlopmaak met CSS spraken me ook aan.

Wellicht zal dit project niet het enige zijn waar ik mij in de nabije toekomst mee bezig zal houden, maar het zal wel mijn hoofdproject zijn. Hoe ver ik het nu precies ga brengen weet ik niet nog niet. Ik heb geen ervaring met het maken van deze systemen en enkel ervaring met het gebruiken van deze systemen als student. Verder zal ik het moeten doen met wat er op het internet over te vinden is. Maar ik ga zo goed mogelijk mijn best doen om het op een applicatie te laten lijken die daadwerkelijk gebruikt zou kunnen worden. Mogelijk wordt het zelfs een applicatie die daadwerkelijk gebruikt KAN worden.

Maar dat zien we nog wel. Voor nu, verwacht regelmatige updates over dit project (ik zal minimaal een bericht per week publiceren, maar niet per se allemaal over dit project), totdat ik het als compleet beschouw. Dat is alles voor nu.

Tot de volgende keer!