[Java] Properties

Pagina: 1
Acties:

  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 15:42
Ik wil in mijn applicatie gebruik gaan maken van java.util.Properties om resources (component labels, berichten etc.) presistent te maken, zodat die niet hard-coded in m'n klasses rondzweven. Ook ondersteuning voor meerdere talen is dan relatief eenvoudig. Nou vroeg ik me af hoe je zoiets het beste kan implementeren.


Alternatief 1:

In iedere klasse die van properties gebruik wil maken een load mechanisme implementeren, waarmee een properties file ingelezen kan worden. Deze properties file is dan specifiek op die klasse gericht.

Dit lijkt mij persoonlijk niet erg handig, omdat ik dan alle klasses langs moet lopen en in iedere klasse steeds dezelfde methode moet implementeren. Daarnaast krijg je een wildgroei aan properties files en voor iedere instantie van een bepaalde klasse wordt inhoud van de properties file opnieuw in het geheugen gezet.


Alternatief 2:

Een singleton klasse ResourceManager aanmaken die bij het starten van de ppliactie één properties file inleest voor de hele applicatie en een uitlees mechanisme aanbiedt.

óf

Dezelfde ResourceManager die op klasse basis eenmalig een propertie file inleest wanneer dat nodig is en deze bewaard tot er geen instanties van die klasse meer aanwezig zijn.

Een van deze varianten lijkt mij persoonlijk beter geschikt. De eerste variant heeft als nadeel dat de applicatie misschien wat traag opstart en meer geheugen gebruikt, omdat er overbodige resources geladen worden. Daarnaast moet je bij het wijzigen, toevoegen of verwijderen van een klasse de hele file doorspitten en aanpassen. De tweede variant heeft als nadeel dat je weer met een scheepslading verschillende resource files zit.


Alternatief 3:
Ik heb ook nog iets gelezen over ResourceBundles, maar dat was voor mij niet helemaal duidelijk. Misschien kan iemand wat meer uitleg geven over het gerbuik hiervan en de verschillende types.


Hoe zouden jullie dit aanpakken?

  • watzie
  • Registratie: Juni 2001
  • Laatst online: 16-05 15:09
Een kant en klaar advies kan ik niet geven omdat het er sterk van afhangt wat voor applicatie je gaat maken. Is een het applet, een application, of juist een webapplication.

Ik zou me iig geen zorgen maken over resourcegebruik of opstart tijden tenzij je van plan bent om een (meerdere) megabytes grote properties file te maken. Denk eraan je gebruikt hoogstwaarschijnlijk windows of *nix, wat beide 'disk operating systems' zijn. Liever gezegd geoptimaliseerd om dingen van schijf te lezen. De accesstijd is daarmee te verwaarlozen, trust me. Resourcegebruik zou hoogstens een issue zijn als het bijv een applet of client-server applicatie is omdat je dan natuurlijk alles over het netwerk moet sturen, maar then again die gegevens heb je toch nodig en als je ze bijv. als constanten in je programma zet kost het precies evenveel geheugen, je jar wordt navenant groter dus ook de kb/s laadtijd, of het nou in je jar of in een losse file zit.

Class based properties... tja ik zou het niet doen, je geeft al aan: da's nogal veel boekhouding en over het algemeen gebruik je properties juist omdat je ze op meer dan 1 plaats nodig hebt (specifieke gevallen daargelaten). Maar als alternatief voor constants bij regulerende klasses kan het de moeite waard zijn, ligt weer aan wat je wil maken..

De singleton is een goed idee. Je kan die dan optimaliseren, zodat ie bijvoorbeeld een hashmap bevat (als cache) die de eerste keer dat een property nog niet geladen is deze meteen in een hashmap bewaart en daarna dus niet meer naar de schijf hoeft. Als je meerdere properties files wilt gebruiken, kun je voor elke files een aparte map gebruiken (ipv meerdere singletons), met of voor elke map een aparte getter, of een parameter aan de getter toevoegen. Je moet dan wel rekening houden met of je wilt dat de properties live (dus terwijl je programma runt) geedit kan worden. Je zou dan een reset functie kunnen inbouwen die je ergens met een knopje kan aanroepen, of je laat de getter op je singleton om de zoveel tijd even naar de file date van je propertie file kijken om te detecteren of er iets veranderd is (en dan de hashmap(s) weggooien)..

Een resourcebundle is een gelijkwaardige keuze. Dat is in principe niks anders dan een standaard interface op properties, die je nog steeds zelf moet implementeren dus ook daar kun je bijvoorbeel een map backed mechanisme inbouwen. Resourcebundles zouden vooral een goede keuze zijn als je een web applicatie maakt. I18n, jstl of struts tags bijvoorbeeld die je gebruikt in je jsp's kunnen dan gebruik maken van de resourcebundle die je in je web.xml cq struts-config.xml definieert, en daarmee wordt alles transparant behind the scenes afgehandeld.

Tenslotte: aangezien je de properties files kunt vullen zoals je wilt (alles voor de = is de sleutel, alles erna de waarde) zou ik zeggen maar meerdere files mits er een logische scheiding tussen zit (zoals een nederlandse properties files, een engelse etc.)

De 'classbased techniek' kun je best in 1 properties file zetten, dan prefix je properties gewoon als volgt
nl.tweakers.Wauw.welkom=Wauw een tweaker!
nl.fok.Wauw.welkom=Oh nee een fok!er

Je laat de getter dan het klasse stukje (of wat de prefix ook voorstelt) bepalen, iets van myResources.getInstance().get(this, "welkom");

Ook een leuk mechanisme om bijvoorbeeld als je een (web) applicatie hebt die je op meerdere servers draait, zeg een test en een productieserver. Je zet dan in je file
testserver.databaseinitstring=sybase.test.mydomain:TDS:5001,database1
productieserver.databaseinitstring=sybase.test.mydomain:TDS:5001,database

en in je web initialiser zet je een myResources.setServer("testserver")
waarna je myResources.getInstance().get("databasinitstring") automatisch de goede resource selecteert door getServer() ervoor te plakken. Nooit meer je deployment hoeven aan te passen :-)

anyway hoop dat dit een beetje helpt.

[ Voor 5% gewijzigd door watzie op 16-12-2004 21:40 . Reden: typefoutjes ]


  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 15:42
Bedankt voor de informatie! :)
Ik was inderdaad wat gerust over performance problemen, maar dat zou dus geen probleem moeten zijn? Geheugengebruik zal inderdaad niet explosief groeien aangezien het om tekst data gaat. Toch wil ik wel zo efficënt mogelijk te werk gaan. Uit principe :P

Het gaat overigens om een locale java applicatie, dat was ik vergeten te vermelden. Het is trouwens niet de bedoeling dat vanuit de applicatie de properties files gewijzigd gaan worden. Voor het bijhouden van instelingen zou ik zelf eerder java.util.pref.* gebruiken.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

FallenAngel666 schreef op donderdag 16 december 2004 @ 21:52:
Bedankt voor de informatie! :)
Ik was inderdaad wat gerust over performance problemen, maar dat zou dus geen probleem moeten zijn? Geheugengebruik zal inderdaad niet explosief groeien aangezien het om tekst data gaat. Toch wil ik wel zo efficënt mogelijk te werk gaan. Uit principe :P
Premature optimization is the root of all evil

[ Voor 9% gewijzigd door Alarmnummer op 16-12-2004 22:00 ]


  • watzie
  • Registratie: Juni 2001
  • Laatst online: 16-05 15:09
Lol daar ben ik het principieel mee eens. Met de kanttekening dat als je een beetje thuis bent in code optimalisatie en vantevorden weet dat bepaalde manier van werken/bepaalde klasses/patronen 'duur' 'duurder' 'duurst' zijn is het natuurlijk wel normaal dat je uitjezelf dat soort constructies vermijdt en door iets net zo makkelijks maar snellers vervangt.

Maar inderdaad, primary rule of programming: first make it work, as straightforward as possible, in a way everyone can instantly understand. Then improve. And only then optimize if you find a bottleneck.

  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 15:42
Hahaha! :)
Klopt natuurlijk wel.
Ik moet daar sowieso toch verschrikkelijk op letten, want ik heb de vervelende eigenschap om me volledig op triviale details te storten terwijl het doel dat ik eigenlijk wil bereiken nog lang niet bereikt is...

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Ik let er in grote lijnen wel op. Ik maak datastructuren waarvan ik weet dat er niet achterlijk onnodig veel cputijd/geheugen wordt verbruikt, maar dat zijn vaak van die standaard oplossingen die de code niet onduidelijker maken (vaak zelfs duidelijker zoals bv met maps vs lists).

Maar ik zit niet meer te neuken op iedere bit omdat het nog sneller moet. Als het maar snel genoeg is.

Soms kan het trouwens wel een uitdaging zijn om iets steeds sneller te krijgen. Ik ben al een tijdje bezig met oa een Prolog compiler en ik zit nu tegen de 0.5 GLIPS (Giga Logical Inferences Per Second) aan terwijl ik met nog geen duizendste van die snelheid ben begonnen. 8 queens probleem deed mijn pc de hele nacht over en nu is het in 1.1 seconde. Maar ik ben nog niet klaar, ik wil minimaal 1 GLIPS en zeker met wat recent opgedane ideeen zit dat er wel in. Dus optimalisatie kan wel leuk zijn... Maar ik doe het alleen op plekken waar het nodig is.

[ Voor 42% gewijzigd door Alarmnummer op 16-12-2004 22:29 ]


  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 15:42
Ik heb de volgende aanpak gekozen:

Ik heb een Singleton klasse ResourceManager gemaakt.

Inlezen:

Deze kan op basis van "fully qualified" class names (om te voorkomen dat voor klasses met dezelfde naam uit verschillende packages dezelfde properties wordt ingelezen) een XML properties file inlezen. Deze file moet dan wel in dezelfde package staan als de ResourceManager.class file (welke package dat is wordt dynamisch bepaald). Het is ook mogelijk om een XML properties file in te lezen a.h.v. een absolute padverwijzing. Er kan gekozen worden om de ResourceManager het Properties object bij te laten houden, zodat het XML bestand niet voor iedere instantie van een klasse opnieuw wordt ingelezen.


Waardes opvragen:

Er kan een default taal ingesteld worden (standaard is dit Engels), zodat alle lees operaties een waarde terug gegeven in die taal.
Het is ook mogelijk om per lees operatie een taal te specificeren.
Om meerdere key samenstellingen te ondersteunen kan er ook een default seperator ingesteld worden (standaard is die: _ ).


Ik heb de source online gezet.


Zelf ben ik niet helemaal tevreden over die public static finals die een talen aangeven, omdat de mate van taalondersteuning nu afhankelijk is de ResourceManager en wanneer je een nieuwe taal wilt toevoegen moet je die klasse aanpassen. Geen ingrijpende aanpassing, maar toch. Daarnaast is het niet typesafe. Ik weet echter niet hoe ik dit beter kan oplossen.

Er zijn vast nog wel meer gebreken, dus schiet maar lek! :)

[ Voor 3% gewijzigd door Kwistnix op 17-12-2004 22:34 ]

Pagina: 1