[j2ee/alg] wat te doen bij een (programmeer) fout.

Pagina: 1
Acties:

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Wat ga je doen op het moment dat er een programmeerfout (bv een NullPointerException) optreed in een server applicatie. Vaak onstaat zo`n fout ergens diep in het systeem en de exception die wordt steeds verder omhoog gegooid totdat je uiteindelijk aankomt bij de uitvoerende thread, maar dan? Op zich kun je een try catch(Throwable) erom plakken en dan de fout opvangen. Bij jdk1.5 kun je en error handler aan de thread plakken (handig als je niet beschikking hebt over code van de thread), maar in principe komt het op het zelfde neer: je weet dat er iets is fout gegaan. En dan? Loggen... en verder doen alsof je neus bloed en verder gaan? De applicatie laten stoppen? Bij normale applicaties is dit niet zo`n probleem omdat hoogstends 1 gebruiker pech heeft.. maar bij een server applicatie gaat die vlieger niet op. Als de server down gaat, dan heb je een probleem..

[edit]
Ik heb verder geen behoefte aan 'advies' van mensen die er geen ervaring mee hebben.

[ Voor 20% gewijzigd door Alarmnummer op 29-10-2004 13:02 ]


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 11:34

pjvandesande

GC.Collect(head);

Altijd je errors loggen, windows heeft hier een appart logsysteem voor (anderen OS'en ook). Hier maak ik altijd gebruik van.

De applicatie kun je stoppen als het noodzakelijk is. Dit natuurlijk proberen om uit te sluiten, je wilt een server app niet zomaar sluiten. Het process wat in gang is zou ik opnieuw proberen te starten, mits mogelijk natuurlijk. Dus gewoon nog een keer proberen.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
questa schreef op 29 oktober 2004 @ 13:02:
Altijd je errors loggen, windows heeft hier een appart logsysteem voor (anderen OS'en ook). Hier maak ik altijd gebruik van.
Uiteraard.. ik maak verder gebruik van Log4j om alle errors (en andere meuk) te loggen.
De applicatie kun je stoppen als het noodzakelijk is.
En hoe wil je dit bepalen? Een nullpointerexception kan bv onstaan omdat in een proces iets mis is gegaan met een of ander intern object (dus niemand heeft er last van behalve het proces zelf). Maar het zou net zo goed een algemener object kunnen zijn (dus iedereen heeft er last van/gaat er eventueel last van krijgen)

Als de exception tot het allerhoogste nivo is doorgesijpeld, dan kan je niet zien hoe erg die fout was. En verder is het erg ongebruikelijk om zelf runtime exceptions op te gaan vangen.
Dit natuurlijk proberen om uit te sluiten, je wilt een server app niet zomaar sluiten. Het process wat in gang is zou ik opnieuw proberen te starten, mits mogelijk natuurlijk. Dus gewoon nog een keer proberen.
Ik kan bij een runtime exception niet de garantie meer geven dat het systeem in een consistente toestand is achtergebleven. Moet ik dan verder gaan met een systeem die in een eventuele verkeerde toestand kan verkeren?

[ Voor 8% gewijzigd door Alarmnummer op 29-10-2004 13:09 ]


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Zelf probeer ik zo goed mogelijk de exceptions op een zo laag mogelijk niveau af te vangen. Wel gooi ik dan soms een nieuwe exception op, maar dan weet ik iig op een hoger niveau zeker dat er geen "vreemde" exceptions opkomen.

Natuurlijk zal er altijd wel ergens een exception kunnen ontstaan die je niet verwacht had en dat is dan ook de situatie waar je op doelt. Maar het hangt er helemaal van af waar de exception optreedt, in mijn DAO-klassen vang ik bijv alle exceptions op en doe ik middels een finally een roll-back van de transaction. Behalve dat het gelogged wordt doe ik er niet meer mee dan dat.
Ik ben er helaas nog niet aan toe gekomen om een fail-safe systeem op te zetten dat zodra de database onbereikbaar is, de applicatie in een of andere onderhouds-modus zet, maar dat zit nog wel in de todo.
Andere problemen die de applicatie onbruikbaar maken kan ik me eigenlijk niet echt voorstellen.

Programmeerfouten moet je imho niet in het reguliere foutafhandelingsprocess opnemen, want die hoor je niet te verwachten en exceptions voor niet werkende verbindingen enzo wel ;)
Daarbij komt nog dat het volgens mij vrijwel onmogelijk is om een specifieke exception als een programmeerfout aan te merken binnen de applicatiestuurcode.

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 11:34

pjvandesande

GC.Collect(head);

Alarmnummer schreef op 29 oktober 2004 @ 13:06:
[...]

Uiteraard.. ik maak verder gebruik van Log4j om alle errors (en andere meuk) te loggen.
Kijk, dat is goed. B)
[...]

En hoe wil je dit bepalen? Een nullpointerexception kan bv onstaan omdat in een proces iets mis is gegaan met een of ander intern object (dus niemand heeft er last van behalve het proces zelf). Maar het zou net zo goed een algemener object kunnen zijn (dus iedereen heeft er last van/gaat er eventueel last van krijgen)

Als de exception tot het allerhoogste nivo is doorgesijpeld, dan kan je niet zien hoe erg die fout was. En verder is het erg ongebruikelijk om zelf runtime exceptions op te gaan vangen.
Dit is dus lastig te bepalen. Je zou dmv een boolean in een custom exception type kunnen aangeven of dit echt een ernstige exception is zodat de app afgesloten moet worden of juist niet. Maar dit is een lastig prenciepe omdat je ook niet echt weet wat er opnieuw gestart moet worden.
Dus je zou de applicatie ook kunnen restarten. En in de laatste staat laten terug keren waarvan je weet dat er niets mis is gegaan. Dus na elke transactie of status weiziging dit bijhouden en in deze staat terug keren zeg maar.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
ACM schreef op 29 oktober 2004 @ 13:13:
Zelf probeer ik zo goed mogelijk de exceptions op een zo laag mogelijk niveau af te vangen.
Normale fouten wel.. maar programmeer fouten niet. Ik hoop dat jouw code niet vol staat met try catch(RuntimeException) puur en alleen omdat jij misschien wel een index fout hebt gemaakt.. of een met een null loopt te pielen.
Behalve dat het gelogged wordt doe ik er niet meer mee dan dat.
Idd.. en dat is dus ook precies het gene waar ik mee zit. Ik kan geen garantie geven dat de objecten nog wel in een goeie toestand zijn achtergebleven omdat je normale objecten niet transactioneel zijn.
Programmeerfouten moet je imho niet in het reguliere foutafhandelingsprocess opnemen, want die hoor je niet te verwachten en exceptions voor niet werkende verbindingen enzo wel ;)
Om die fouten gaat het mij dus.. Wat moet je doen op een server op het moment dat je een programmeerfout voor de kiezen krijgt. De techneut in me die zegt.. hup.. server down.. en opnieuw starten. Maar wat zijn de gevolgen hiervan?? Misschien krijgt het bedrijf (waar de server voor draait) grote problemen.. (klanten lopen weg... slechte naam.. geld weg) blabla. Dan nog even doorgaan met een misschien rotte server en dan tot een later tijdstip wachten (als er minder mensen bv zijn).. en dan opnieuw opstarten?

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 11:34

pjvandesande

GC.Collect(head);

Alarmnummer schreef op 29 oktober 2004 @ 13:18:
[...]
Idd.. en dat is dus ook precies het gene waar ik mee zit. Ik kan geen garantie geven dat de objecten nog wel in een goeie toestand zijn achtergebleven omdat je normale objecten niet transactioneel zijn.
Daarom elke keer een goede status loggen zeg maar, en bij zo'n exception de server opniew opstarten met de laatst bekende status. En natuurlijk altijd een roll-back uitvoeren.

  • bigbeng
  • Registratie: Augustus 2000
  • Laatst online: 26-11-2021
Ik heb geen specifieke ervaring met dit soort problemen, maar ik heb natuurlijk wel een idee over hoe ik het zou kunnen aanpakken. Mag ik reageren, ah toe? O-) :)

Ik ga ervan uit dat het threadproces slim genoeg is opgezet om te weten dat als hij onderuit gaat door een programmeerfout dat dan de applicatie zou moeten stoppen, of alleen het threadproces zelf. Je kan dit dus doorgeven naar de main thread door zelfgedefinieerde exceptions. Ik zou de faulty thread dus de exception laten loggen en vervolgens wrappen in een eigen exception (Bijvoorbeeld ServerCriticalException ofzoiets) en die omhoog gooien.

  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Het hangt wel af over wat voor soort server application je praat. Wanneer je over een typische stateless 3-tier applicatie praat met webservices waarin elke webservice methode een transactie is op enkel en alleen database(s), dan mag het optreden van een runtime exception de server niet in een inconsistente toestand achterlaten. Je hoeft een dergelijke exception dan in principe ook niet op te vangen, deze wordt door het systeem zelf gelogd en doorgepropageerd naar de client. De rest van de clients zijn daarvan geïsoleerd.

Wat betreft serverside applicaties die niet geheel stateless zijn (of niet aan ACID eigenschappen voldoen), dan zou ik dat niet weten. Daar heb ik dan ook geen ervaring mee. Maar ik heb zo het idee dat wat je ook doet, het altijd verkeerd is omdat op het niveau waar je de beslissing wilt maken, je geen gefundeerde keuze kan maken vanwege te weinig informatie.

Tenzij je die kennis gaat toevoegen. Bijvoorbeeld regels opstellen over de compositie van componenten die aangeven wat er moet gebeuren als een component faalt met runtime errors... of dat ook practisch is zou ik niet weten.

[ Voor 8% gewijzigd door Infinitive op 29-10-2004 13:30 ]

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Alarmnummer schreef op 29 oktober 2004 @ 13:18:
Idd.. en dat is dus ook precies het gene waar ik mee zit. Ik kan geen garantie geven dat de objecten nog wel in een goeie toestand zijn achtergebleven omdat je normale objecten niet transactioneel zijn.
Ik heb maar weinig niet-transactionele objecten die een langere levensduur hebben dan de specifieke request, dus daar heb ik geen ervaring mee. Uiteraard heb ik wel e.e.a. aan objecten dat een langere levensduur heeft, maar die worden meestal toch weer niet om hun status, maar om hun functionaliteit gebruikt (de DAO's bijv).

Omdat mijn applicatie dus voornamelijk een webapplicatie is, heb ik sowieso veel meer met request-based programmeren te maken en moet de state van objecten aan het eind van de request afgehandeld zijn. Daarna zijn ze niet meer nodig. Hibernate cached ze nog wel voor me, maar voor het gemak ga ik er maar van uit dat daar geen fouten in zitten.

De enige dingen die ik me zo voor de geest kan halen waar het mis mee kan gaan zijn de databaseverbindingen en caches. Van de laatste wordt sowieso al gecontroleerd of de resulterende variabele null is om de boel daarna eventueel uit de database te vissen.
Om die fouten gaat het mij dus.. Wat moet je doen op een server op het moment dat je een programmeerfout voor de kiezen krijgt. De techneut in me die zegt.. hup.. server down.. en opnieuw starten. Maar wat zijn de gevolgen hiervan?? Misschien krijgt het bedrijf (waar de server voor draait) grote problemen.. (klanten lopen weg... slechte naam.. geld weg) blabla. Dan nog even doorgaan met een misschien rotte server en dan tot een later tijdstip wachten (als er minder mensen bv zijn).. en dan opnieuw opstarten?
Dat zal je per applicatie opnieuw moeten bedenken. Je kan de boel met een vriendelijke melding in een onderhoudsmodus zetten, liever dat dan dat er ernstige problemen ontstaan (bij een bankapplicatie ofzo). En die ook door beheerders met de hand laten uitschakelen (desnoods met een herstart van de applicatieserver)
Of je kan de fout loggen/mailen en verder gewoon doorgaan omdat eventuele fouten hooguit wat vervelend voor de gebruiker zijn, maar niet ernstig genoeg om zijn plezier te vergallen. Eventueel laat je nog weten dat je applicatie door een nog niet onderzochte fout in een instabiele modus is terechtgekomen en dat de gebruiker daar niet van moet schrikken ;)

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
questa schreef op 29 oktober 2004 @ 13:23:
[...]
Daarom elke keer een goede status loggen zeg maar,
hmmm... duidelijk (not).
en bij zo'n exception de server opniew opstarten met de laatst bekende status.
Misschien te doen bij hele kleine servertjes.. maar bij normale servers (met een complexe flow van data) kan je dat wel op je kont schrijven.

vraag: heb jij hier ervaring mee? ja/nee... zo nee.. zie dan mijn 1e post. No offence.. maar ik heb niets aan typisch got geneuzel waarbij iedereen de behoefte heeft om maar wat te kladden. Maar ik wil weten hoe andere mensen (die er ervaring mee hebben) mee opgaan.

  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 11:34

pjvandesande

GC.Collect(head);

Alarmnummer schreef op 29 oktober 2004 @ 13:30:
[...]

hmmm... duidelijk (not).
Je kunt natuurlijk elke keer een status loggen, nouja loggen is niet het goede woord, maar de status van de server elke keer opslaan.

Dus dat jij de server kan rebooten en hem opnieuw starten in de laatste goede toestand.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
bigbeng schreef op 29 oktober 2004 @ 13:25:
Ik heb geen specifieke ervaring met dit soort problemen, maar ik heb natuurlijk wel een idee over hoe ik het zou kunnen aanpakken. Mag ik reageren, ah toe? O-) :)

Ik ga ervan uit dat het threadproces slim genoeg is opgezet om te weten dat als hij onderuit gaat door een programmeerfout dat dan de applicatie zou moeten stoppen, of alleen het threadproces zelf.
Was dat maar zo (dat die slim genoeg was). Helaas.. je krijgt op het allerlaagste nivo een runtime exception voor de kiezen...en als niemand er iets mee doet.. tja.. dan houd die thread het voor gezien (na het door de exception exiten van de run methode is de thread 'dood' ). Wat ga je dan doen?
Je kan dit dus doorgeven naar de main thread door zelfgedefinieerde exceptions.
Wat heeft die 'main' thread er nog mee te maken? In veel j2ee applicatie wordt die 'main' thread gebruikt om de applicatie op te starten en daarna handelen allerlei worker threads de requests af. Die mainthread is niet interessant meer.
Ik zou de faulty thread dus de exception laten loggen en vervolgens wrappen in een eigen exception (Bijvoorbeeld ServerCriticalException ofzoiets) en die omhoog gooien.
Een 'worker' thread kan niet een exceptie in een andere thread plaatsen. Dus wat jij zegt wil niet.


nogmaals... ik wil graag dat mensen reageren die er ervaring mee hebben.

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

Alarmnummer schreef op 29 oktober 2004 @ 13:30:
[Misschien te doen bij hele kleine servertjes.. maar bij normale servers (met een complexe flow van data) kan je dat wel op je kont schrijven.
Zodra je een nullpointer exception krijgt, of gewoon in non-java een ordinaire segfault dien je gewoon de applicatie af te sluiten, aangezien het gedrag vanaf dan niet meer te voorspellen is. Op deze manier krijg je ook het snelst de bugs uit de applicatie. Ik zelf genereer een stacktrace indien mogelijk, da's altijd beter dan niets.
vraag: heb jij hier ervaring mee? ja/nee... zo nee.. zie dan mijn 1e post. No offence.. maar ik heb niets aan typisch got geneuzel waarbij iedereen de behoefte heeft om maar wat te kladden. Maar ik wil weten hoe andere mensen (die er ervaring mee hebben) mee opgaan.
Een NPE duidt gewoon op slechte checking, en is gewoon een (grove) ontwerpfout. Argumenten aan functies dien je gewoon in de functie zelf te checken op geldige input, zelf doe ik dat met assert()'s. In Java kan het allemaal nog wat mooier, en vooral uitgebreider.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
questa schreef op 29 oktober 2004 @ 13:35:
[...]
Je kunt natuurlijk elke keer een status loggen, nouja loggen is niet het goede woord, maar de status van de server elke keer opslaan.
Denk nou even goed na. Stel dat mijn server 50 mb geheugen in beslag neemt met 100.000 objecten.. moet ik dan bij iedere call dat hele geheugen gaan dumpen zodat ik het de volgende keer kan 'inladen'?

Stel dat ik 10 calls naar buiten doe dan heb ik al een 500 mb gelogt... wees eerlijk... dat is toch niet serieus te nemen?

Ik vind het leuk dat iedereen wil replyen.. maar ik stoor me (vaak) aan het feit dat mensen antwoord geven die er zelf nog niet zoveel ervaring mee hebben. Het is voor een ander (die ook vragen heeft) lastig om te achterhalen of die ene iets zinnigs zegt.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
igmar schreef op 29 oktober 2004 @ 13:42:
[...]
Zodra je een nullpointer exception krijgt, of gewoon in non-java een ordinaire segfault dien je gewoon de applicatie af te sluiten, aangezien het gedrag vanaf dan niet meer te voorspellen is.
Alarmnummer zegt: _/-\o_

De manager zegt: 8)7 :X }:O
Een NPE duidt gewoon op slechte checking, en is gewoon een (grove) ontwerpfout.
Een nullpointer fout kan ook duiden op een goeie checking.. maar dat terzijde.. en het is dikke bullsh*t dat het iets met een ontwerp te maken heeft.
Argumenten aan functies dien je gewoon in de functie zelf te checken op geldige input, zelf doe ik dat met assert()'s. In Java kan het allemaal nog wat mooier, en vooral uitgebreider.
Mee eens... maar helaas is niet alle software perfect. Je kunt dan wel moeilijk lopen doen hoe het allemaal mooier, beter en perfecter kan.. maar in de praktijk zitten er fouten in software. De vraag is dus wat je gaat doen met een fout (die in de praktijk vaak voorkomt) gaat doen.

[ Voor 3% gewijzigd door Alarmnummer op 29-10-2004 13:47 ]


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 11:34

pjvandesande

GC.Collect(head);

Alarmnummer schreef op 29 oktober 2004 @ 13:43:
[...]

Denk nou even goed na. Stel dat mijn server 50 mb geheugen in beslag neemt met 100.000 objecten.. moet ik dan bij iedere call dat hele geheugen gaan dumpen zodat ik het de volgende keer kan 'inladen'?

Stel dat ik 10 calls naar buiten doe dan heb ik al een 500 mb gelogt... wees eerlijk... dat is toch niet serieus te nemen?

Ik vind het leuk dat iedereen wil replyen.. maar ik stoor me (vaak) aan het feit dat mensen antwoord geven die er zelf nog niet zoveel ervaring mee hebben. Het is voor een ander (die ook vragen heeft) lastig om te achterhalen of die ene iets zinnigs zegt.
Hangt van de data af, als het noodzakelijk data is zou ik dit altijd loggen. Je moet natuurlijk eerst kijken of je calls kan afmaken en natuurlijk alleen noodzakelijke data herladen.

Niet bij elke server is dit natuurlijk mogelijk, hangt van de grootte af en de hoeveelheid data etc.

* pjvandesande bedoelt dit trouwens serieus

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
questa schreef op 29 oktober 2004 @ 13:51:
[...]
Hangt van de data af, als het noodzakelijk data is zou ik dit altijd loggen.
De enigste plek waarin data komt te staan over de eventuele voortgang van een proces is de database. Als ik bv 10 emails moet versturen (en het is erg belangrijk dat ze eenmalig en gegarandeerd verstuurd worden), dan zet je ze in de database en kan je na bv het crashen na het 5e mailtje... de volgende keer die andere 5 versturen. De database is de enigste plek waarin je dit zou moeten doen.. (kan je fijn gebruik maken van alle acid eigenschappen.. en loop je niet te prutsen met allerlei eigen baksels).

Maar dit is niet zozeer het probleem..
Het probleem zit hem niet in wat te doen na een server crash.. het probleem zit hem in het : wat te doen bij een server 'fout': stoppen.... doorgaan...

[ Voor 15% gewijzigd door Alarmnummer op 29-10-2004 13:58 ]


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Alarmnummer schreef op 29 oktober 2004 @ 13:46:
De vraag is dus wat je gaat doen met een fout (die in de praktijk vaak voorkomt) gaat doen.
En de wedervraag is dan wat voor applicatie is het, en hoe afhankelijk is de staat van het geheel, van de staat van een enkele foutgelopen thread?

Er is geen eenduidig antwoord op de vraag "Wat doe je ermee?". Want soms boeit het gewoon nauwelijks dat het een kwartiertje niet goed loopt, terwijl het soms niet eens een tweede keer ook maar het risico op herhaling mag hebben.

Wat ik zelf wil gaan bekijken voor mijn Struts-based webapp is om een algemene systeemstatus bij laten houden en de RequestPreProcessor daar bij elke request naar laten kijken.
Die systeemstatus kan je in een of andere (static) omgeving bijhouden en kan dan door een of andere exceptionhandler gezet worden.

De statussen kan je bijvoorbeeld laten bestaan uit "full-access", "read-only-access", "admin-only-access", "no-access". De read-only is voor je het vermoeden hebt dat er iets fout gegaan is, maar je niet verwacht dat het heel erg is: men kan dan iig nog informatie lezen. De admin-only is natuurlijk voor het debuggen/onderzoeken. En de no-access is voor als het helemaal in de soep is gelopen en je een restart nodig hebt.

Als je dat soort zaken wilt zien te automatiseren, moet je alles wat je niet in die full-access-modus wil laten doorgaan al als verdacht genoeg markeren om je server te herstarten of je webapp te redeployen. Maar dan heb je alleen maar de status hersteld tot een geldige status, zonder dat je ook maar de fout hebt onderzocht. 't Heeft iig niet mijn voorkeur om te doen.

  • DaCoTa
  • Registratie: April 2002
  • Laatst online: 12:07
Wat je wilt doen is afhankelijk van de soort error. Programmeerfouten zijn problemen waar ik over het algemeen geen mooie afvangroutine voor heb, omdat je nooit kunt weten waar en hoe ze zich uitten. Het zijn nou eenmaal programmeerfouten en deze moeten er gewoon asap uit. Op de cruciale punten, (in J2EE) een catch block met tracedump voor snelle foutoplossing en binnenkort met de mailmodule van log4j. In dit geval gaat de server dus niet down, maar heeft alleen deze gebruiker pech. En alle anderen die op dezelfde bug stuiten.

Andere problemen (denk aan bijvoorbeeld een database die down is) worden zo goed als het kan vertaald maar de gebruiker. Bij fatal errors worden de gebruikers uitgelogd en doorverwezen naar een noodscherm (denk aan testbeeld voor t.v.).

Kortom, de server gaat nooit down. Problemen kunnen buiten hem opgelost worden en het opnieuw aanzetten van de server kost dan alleen maar tijd. Bij iedere request wordt dus weer gekeken of de database actief is zodat de boel zsm weer kan gaan draaien.

De applicaties waar ik mee werk zijn vaak combinaties van user based en process based en alle foutafhandeling gaat eigenlijk op eenzelfde manier. Enige verschil is de moeite die wordt gedaan om een leesbare foutmelding op het scherm te toveren voor de gebruiker. Processen worden (meestal) niet gevolgd door de gebruiker, dus deze hoeft geen taalafhankelijke foutmelding te krijgen, maar die kan best in geval van nood stoppen met een SQLException ofzo.

  • momania
  • Registratie: Mei 2000
  • Laatst online: 06:42

momania

iPhone 30! Bam!

Qua echte server code heb ik er ook niet zo veel ervaring mee, maar ik weet wel andere dingen die mij goed geholpen hebben.

Vaak kun je je objecten die bijvoorbeeld als server modules dienen allemaal wel laten extenden van 1 basis class (of een paar verschillende types natuurlijk). Ik maak dan meestal in die basis class een exception handle method die aangeroepen worden in de catch van elke try-catch combi die je gewoon in elke method van een class moet hebben. (of meerdere van die blokken om zelfs te weten in welk stuk van een method het fout is gegaan en dat aan te duiden met een of andere code).

Die handle method wrapped de orginele exception in een eigen type exception en gooit deze verder. Elke bovenliggende class die dan deze exception krijgt zal weer de exception handle method in gaan, maar omdat deze herkent dat het een eigen type exception is, hoeft deze 'm ook alleen maar door te gooien.

Voordeel hiervan is iig dat je je afhandeling iig eenduidig kan doen.
De eigen exception houd dan een ErrorEvent vast (ongeveer zoals Struts het doet), waarin ik iig de SourceClass name stop waar de fout in opgetreden is. Deze kan je gewoon middels reflection opvragen, wat in geval van exception handling best mag. :)

Verder probeer je zo veel mogenlijk de info van alle objecten die bij jouw 'server transactie' horen de waardes in je logging te dumpen.

Het gaat natuurlijk om het volgende:
Bij een reguliere fout die netjes afgevangen worden, kun je de begruiker iig (al is het voor een gebruiker soms in onverklaarbare code) laten zien wat er mis is gegaan. Hij kan dan adv die melding eventueel een helpdesk bellen waar die fouten bekend zijn en die weten wat een work around zou moeten zijn.

Bij echte programmeer fouten wordt dit toch een stuk lastiger, dus is het iig het belangrijkst dat je eigen exceptionhandling zo is dat een gebruiker de fout kan door bellen en jij als programmeur eingelijk bijna direct moet weten waar het fout is gegaan. Daarbij kan je dan met informatie als sourceclass en tijd, direct gericht in de logging zoeken en daar de gegevens lezen die op dat moment bij die transactie hoorde om het zou zelf te kunnen reproduceren. :)

Neem je whisky mee, is het te weinig... *zucht*


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
ACM schreef op 29 oktober 2004 @ 13:58:
[...]
En de wedervraag is dan wat voor applicatie is het, en hoe afhankelijk is de staat van het geheel, van de staat van een enkele foutgelopen thread?
Hmmm tja... Je kunt heel slecht een uitspraak doen bij de allereerste call van een thread (de run methode) wat voor gevolgen die fout op dit moment heeft voor de rest van het systeem. En verder is deze aanname erg slecht te vertalen naar een systeem dat steeds verder groeit... misschien was er geen afhankelijkheid.. later wel.. maar de actie wat ondernomen gaat worden die verandert niet meer.
Als je dat soort zaken wilt zien te automatiseren, moet je alles wat je niet in die full-access-modus wil laten doorgaan al als verdacht genoeg markeren om je server te herstarten of je webapp te redeployen. Maar dan heb je alleen maar de status hersteld tot een geldige status, zonder dat je ook maar de fout hebt onderzocht. 't Heeft iig niet mijn voorkeur om te doen.
Hmm tja.. kijk.. ik ben niet bang om de server te herstarten. Technisch gezien zit alles wel snor. Ik ben bang voor de niet technische gevolgen...

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

Alarmnummer schreef op 29 oktober 2004 @ 13:46:
Een nullpointer fout kan ook duiden op een goeie checking.. maar dat terzijde.. en het is dikke bullsh*t dat het iets met een ontwerp te maken heeft.
Als je exception vervolgens niet afgevangen wordt heb je aan die goede checking nog zo weinig, en duidt het IMHO op een design probleem. Dat de $manager het niet fijn vind dat de app d'r mee kapt als er dit soort fouten optreden zou ik me weinig van aan trekken, een applicatie die niet meer correct functioneert omdat dit soort fouten niet of niet goed worden afgehandeld is als je het mij vraagt veel erger.
Mee eens... maar helaas is niet alle software perfect. Je kunt dan wel moeilijk lopen doen hoe het allemaal mooier, beter en perfecter kan.. maar in de praktijk zitten er fouten in software. De vraag is dus wat je gaat doen met een fout (die in de praktijk vaak voorkomt) gaat doen.
In Java is het nog simpel. In C / C++ krijg je of een segfault, of onvoorspelbaar gedrag. Nu zijn de tools wel goed, maar ik kies d'r altijd voor om d'r gewoon meteen helemaal mee te stoppen, dan wordt de bug iig gefixed :)

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 08:25

Creepy

Tactical Espionage Splatterer

Alarmnummer schreef op 29 oktober 2004 @ 13:46:
[...]
[...]

Een nullpointer fout kan ook duiden op een goeie checking.. maar dat terzijde.. en het is dikke bullsh*t dat het iets met een ontwerp te maken heeft.
eeh?? Als dat duidt op goede checking, dan lijkt het me dat je de exption kan vangen en afhandelen. En het lijkt me dat het afhandelen van fouten wel degelijk iets met je ontwerp te maken heeft.
Mee eens... maar helaas is niet alle software perfect. Je kunt dan wel moeilijk lopen doen hoe het allemaal mooier, beter en perfecter kan.. maar in de praktijk zitten er fouten in software. De vraag is dus wat je gaat doen met een fout (die in de praktijk vaak voorkomt) gaat doen.
Onverwachte fout: stoppen en eventueel een herstart. Als je zekerheid wilt doe je dat. Ik heb liever een systeem dat NIET draait (of zichzelf herstart) dan een systeem wat foutief draait. Downtime is een stuk makkelijker op te lossen dan foute data in je systeem.

Daarnaast heb je verwachte "fouten". Dit kan je afhandelen en daarna zelf bepalen wat er moet gebeuren.

[ Voor 5% gewijzigd door Creepy op 29-10-2004 14:31 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Creepy schreef op 29 oktober 2004 @ 14:30:
[...]

eeh?? Als dat duidt op goede checking, dan lijkt het me dat je de exption kan vangen en afhandelen. En het lijkt me dat het afhandelen van fouten wel degelijk iets met je ontwerp te maken heeft.
Niet Runtimeexception ja... die niet afgahandeld -> slecht ontwerp.
Runtime exceptions? (en dan moet je lezen programmeer exceptions) Nee.. want die ga je zelf in principe nooit afvangen.

[ Voor 6% gewijzigd door Alarmnummer op 29-10-2004 14:46 ]


Verwijderd

Volgens mij is het heel eenvoudig. Je vangt programmeer fouten simpelweg nooit af.

Als het programma stopt vanwege een onbedoelde null-pointer in een programma is dat prima.

Stel je voor:

code:
1
2
3
4
5
6
7
8
9
10
myObject = null;
int realyimportValue = 0;
try {

   realyimportantValue = myObject.getValue(); // causes nullpointer
} catch (NullPointerException e) {
   log.error("NullPointer catched: " + e.toString());
}

int myNewSalary = calculateMyNewSalary(realyimportValue * 500);


Hoewel netjes gelogd wordt dat de nullpointer optreedt, krijg ik volgende maand wel te weinig salaris!

Het is dan ook prima dat zo'n nullpointer uiteindelijk in de main thread boven komt drijven, het programma doet immers iets wat niet gewenst is. Wil je een nette error melding i.p.v. een lelijke stacktrace of iets dergelijks, vang hem dan af op het hoogste niveau (bijv. in main) en exit de applicatie.

Het is gewoon een bug. En moet gefixt worden alvorens de applicatie weer gebruikt kan en mag worden.

  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Ja maar dit is dan ook niet de manier om fouten op te vangen ;)

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


Verwijderd

Infinitive schreef op 29 oktober 2004 @ 15:08:
Ja maar dit is dan ook niet de manier om fouten op te vangen ;)
Hoe had je het dan gedacht? Kun jij me uitleggen hoe je een fout kunt afvangen die je niet verwacht? Omdat de fout eigenlijk niet kan voorkomen, behalve door een programmeer fout???

  • igmar
  • Registratie: April 2000
  • Laatst online: 12-05 15:46

igmar

ISO20022

Alarmnummer schreef op 29 oktober 2004 @ 14:41:
Niet Runtimeexception ja... die niet afgahandeld -> slecht ontwerp.
Runtime exceptions? (en dan moet je lezen programmeer exceptions) Nee.. want die ga je zelf in principe nooit afvangen.
Precies, aan gezien ze er per definitie voor zorgen dat het verdere verloop van je programma 'undefined' is dien je gewoon verdere executie van het programma te stoppen.

  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Verwijderd schreef op 29 oktober 2004 @ 15:11:
Hoe had je het dan gedacht? Kun jij me uitleggen hoe je een fout kunt afvangen die je niet verwacht? Omdat de fout eigenlijk niet kan voorkomen, behalve door een programmeer fout???
Het probleem bij het stukje code dat je geschetst hebt, is dat je verder gaat met state die mogelijk incorrect is. Het opvangen van fouten heeft alleen zin als je daarmee een inconsistente state kan repareren. Zo niet, dan zou je wel kunnen loggen, maar daarna moet je doorthrowen.

In jouw voorbeeld is in principe de myobject het probleem, hoewel voor dit probleem de inconsistente state alleen de realyimportValue is. Jouw catch hander zou dus iets met die realyimportValue moeten doen om de state voor deze methode te repairen. Of de handler had om de hele code heen moeten staan om maar iets te noemen.

Maar zoals je merkt is dit specifiek voor dit probleem. Je kan dit in het algemene geval niet doen, tenzij je bepaalde garanties hebt wat de affected state is.
Transacties op een database kunnen jouw bijvoorbeeld dit soort isolatie garanties geven. Om het simpel te zeggen: als er iets fout gaat binnen je programma, dan is het geheugen corrupt en de transactie op de database. Je kan dan de fout opvangen door het geheugen overnieuw te initialiseren en de transactie te herstarten.

Het probleem wordt een stuk lastiger wanneer je meerdere applicaties/threads hebt die samen ook wat data delen. Als je weer naar je algemene handler kijkt, dan zou ook de gedeelde data corrupt geraakt kunnen zijn (tenzij je daar weer isolement garanties op hebt). De state repareren is lastig, vermoedelijk moeten de overige threads ook wat zaken repareren. Dit is applicatie specifiek en in sommige gevallen theoretisch onmogelijk.

Kan dit op een algemene manier? Daarvoor heb je weer wat extra aannamen op je omgeving nodig. Bijvoorbeeld alle threads killen en overnieuw een initiele state opbouwen en threads weer starten. Dit komt eigenlijk overeen met een herstart van de totale applicatie. Maar hiervoor heb je dus ook bepaalde consistentie/durability aannamen nodig. Wat een minimale set van aannamen is om dit te bereiken kan ik zo niet zeggen. Want je zult nu bijvoorbeeld moeten garanderen dat er geen gegevens "verloren" zijn gegaan (durability). En wie zegt dat het probleem niet blijft optreden na een herstart?

Om nog maar te zwijgen van dat in een multi-threaded systeem met gesharede state je ook nog met race condities te maken hebt die ervoor kunnen zorgen dat op het moment dat je de fout kan opvallen, het zaakje al niet meer te redden is...

Het zal in de praktijk eenvoudiger zijn de applicatie zo te maken dat je op een willekeurig moment de stekker eruit kan trekken zonder consistentie van de totale applicatie te verliezen. Dan kan je in geval van problemen een herstart doen (onder aanname dat daarmee de "corruptie" ongedaan wordt gemaakt bijv. door een impliciete rollback door de database). Maar dat wil nog niet zeggen dat het nooit mogelijk is om een onverwacht probleem op te vangen. Maar dan zul meer van het systeem moeten vereisen (meer aannamen).

[ Voor 18% gewijzigd door Infinitive op 29-10-2004 16:14 ]

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • B-Man
  • Registratie: Februari 2000
  • Niet online
Ik heb dit probleem als volgt opgelost: (het is tot dusver twee keer voorgekomen, dus zelfs 'proven technology' (tm) ;))
Ik vang op het hoogste niveau alle exceptions af, en verzend als er een exception langskomt een alert per e-mail/sms/vul-zelf-maar-in, kortom: zaken zoals dit kan een machine zonder AI volgens mij niet consequent of consistent oplossen.
Het systeem kan zichzelf opnieuw opstarten, afhankelijk van de opgetreden fout. Als deze bij het starten vervolgens wederom een fout geeft, verhoog ik de prioriteit van de alert, en gaat er nog een 'de deur uit'.
Wat infinitive zegt spreekt natuurlijk voor zich: zoveel mogelijk transactie-georienteerd, en geisoleerd te werk gaan, zodat er zo min mogelijk 'rondzwervende' data is, die verloren kan gaan.
Afhankelijk van de wensen van een klant is er natuurlijk een SLA die aangeeft hoe snel een 'mannetje' het probleem oplost.

Overigens zijn de systemen waarin ik dit toepas over het algemeen geclustered, wat betekent dat uitval van een node niet direct het hele systeem onwerkbaar maakt.

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 19-05 00:34

alienfruit

the alien you never expected

Vast stomme opmerking, maar als ik me goed herriner bevat een Exception een Throwable object, deze heeft weer referenties na andere Throwable. Hierbij kon je vervolgens dmv. een while loop de stacktrace ophalen. Bij mijn weten is ook zoiets vergelijksbaars voor exception, zo kun je op zoek gaan na de eerste Exception helemaal onderaan de lijst (waar de eerste kwam).

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
B-Man schreef op 30 oktober 2004 @ 02:05:
Ik vang op het hoogste niveau alle exceptions af, en verzend als er een exception langskomt een alert per e-mail/sms/vul-zelf-maar-in, kortom: zaken zoals dit kan een machine zonder AI volgens mij niet consequent of consistent oplossen.
Het systeem kan zichzelf opnieuw opstarten, afhankelijk van de opgetreden fout. Als deze bij het starten vervolgens wederom een fout geeft, verhoog ik de prioriteit van de alert, en gaat er nog een 'de deur uit'.
Hier hadden wij ook al aan zitten denken. Weet je of je trouwens of een applicatie zichzelf automatisch kan redeployen op een applicatieserver?
k heb dit probleem als volgt opgelost: (het is tot dusver twee keer voorgekomen, dus zelfs 'proven technology' (tm)
Je bent je roeping misgelopen, je had marketing dude moeten worden ;)

[ Voor 14% gewijzigd door Alarmnummer op 30-10-2004 06:34 ]


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
alienfruit schreef op 30 oktober 2004 @ 02:46:
Vast stomme opmerking, maar als ik me goed herriner bevat een Exception een Throwable object, deze heeft weer referenties na andere Throwable. Hierbij kon je vervolgens dmv. een while loop de stacktrace ophalen.
Jij bent nu de exception chain aan het ophalen en dat is iets anders dan de stacktrace. De stacktrace is niets anders dan een afspiegeling van de environment frame stack op het moment dat een exception is opgetreden.
Bij mijn weten is ook zoiets vergelijksbaars voor exception, zo kun je op zoek gaan na de eerste Exception helemaal onderaan de lijst (waar de eerste kwam).
Iedere exception is een throwable ;)

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 19-05 00:34

alienfruit

the alien you never expected

Ja, en elke exception bevat een stacktrace bij mijn weten. Volgens mij kan je er dan toch wel wat mee :?

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Je kunt die stacktrace veranderen al-dan-niet door een nieuwe exception op te gooien. Ik ben iig wel eens een library tegengekomen die mij exceptions teruggaf die maar tot een bepaald call-level gingen, waardoor ik een fout intern in die library pas met veel moeite (code wijzigen, recompilen, etc) kon achterhalen.

[ Voor 9% gewijzigd door ACM op 30-10-2004 11:29 ]


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 19-05 00:34

alienfruit

the alien you never expected

Ooh, geen idee. Ik doe zulk moeilijke dingen niet in Java, gewoon de simpele spelletjes voor de mobieltjes etc. :)

  • flowerp
  • Registratie: September 2003
  • Laatst online: 04-02 02:01
Ik werk zelf behoorlijk veel in een J2EE omgeving, maar dat zijn altijd web applicaties (geen enterprise app). Wat ik niet snap van deze thread is waarom een hele server inconsequent zou worden. In een servlet of jsp pagina handel ik een request van een client af. Aan de client is een sessie verbonden, die specificiek voor deze client is. Als er ergens wat fout gaat, dan is dat of in een object die nog niet eens session scope heeft, of het is in een object die wel in de sessie staat, maar dan nog is dat alleen een probleem voor die specificieke user.

Hoewel ik nu 2 jaar met J2EE web applicaties werk (1 jaar in loon dienst, en +- 1 jaar op HBO school) zeg ik niet dat ik een hele grote expert ben. Ik zit echter mijn hersenen te pijnigen in welke situatie je dan wel data van andere users of de server zelf zou beschadigen?

In een servlet zou je een instance variabele kunnen gebruiken, en die is per definitie shared. Hier moet je dan wel voorzichtig mee omgaan. Als er een exception in een stuk code optreed wat naar deze instance variable schrijft dan zou je deze meteen weer op een default terug kunnen zetten. Dat je aan het schrijven (toekennen) was betekent namelijk ook dat jij de enige was die dat deed (vanwege de synchroniatie die je dan geregeld hebt) en dat meteen alle variablen die hier mee samen hangen ook gesynchronized zijn. Alle readers staan op dat moment te wachten en zullen nu een default waarde krijgen. Vanwege het stateless http protocol zal een request naar een serverlet van de meegeven waardes in de request moeten afhangen en niet van een serverside state. Je zou dus de request altijd correct moeten kunnen afhandelen, ondanks het feit dat je je servlets instance variablen weer op een default hebt gezet.

Als ik bij bovenstaande redenatie iets over het hoofd zie zou ik dat natuurlijk graag horen :)

Waar ik veel meer bang voor ben is dat fouten niet consequentie data in de DB zetten, en dit hoeft helemaal niet het gevolg te zijn van een exception. Ik had bijvoorbeeld ooit per ongeluk 2 variablen omgedraait gebruikt, zodat de inkomsten voor 1 enkele situatie met de uitgaven omgedraaid werden. Dit kwam pas iets later bij een hogere controlle aan de orde, maar toen was er wel al een week verstreken en de bedragen waren al overgemaakt. Omdat dit geen enkele exception veroorzaakt, viel er ook nix te shutdown-en of te rollback-en.

Om dit op te vangen zou je mischien heel veel integeriteits testen moeten defineren (kan zeker niet altijd op DB niveau) die op een assert achtige wijze heel veel dingen gaan controleren op correctheid?

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


  • B-Man
  • Registratie: Februari 2000
  • Niet online
flowerp: omdat HTTP zaken veelal stateless zijn is het daar ook niet zo'n probleem. Maar wat denk je van server-side processen die 24/7 draaien, en niet (helemaal) atomic zijn? M.a.w.: zodra het wat complexer wordt dan actie-reactie (zoals HTTP) en betrouwbaarheid en uptime een belangrijke (of kritische) rol spelen, loop je al snel tegen van dit soort problemen aan.

Alarmnummer: volgens mij kan een app zichzelf niet redeployen. Is het sowieso niet handiger om een andere tool je app te laten monitoren? De alert/monitoring code is generiek genoeg om buiten je hoofdapplicatie te plaatsen.

  • flowerp
  • Registratie: September 2003
  • Laatst online: 04-02 02:01
B-Man schreef op 30 oktober 2004 @ 16:29:
flowerp: omdat HTTP zaken veelal stateless zijn is het daar ook niet zo'n probleem. Maar wat denk je van server-side processen die 24/7 draaien, en niet (helemaal) atomic zijn?
Dat begrijp ik ja. Alarmnummer, over wat voor soort server side process gaat het dan precies? Uiteindelijk handelt elke server requesten af. Deze zouden sowieso al redelijk onfhankelijk van elkaar moeten zijn (je wilt niet alle requesten van clients op elkaar laten wachten omdat je alle resources moet locken).

Je zou zeggen dat een server voornamelijk persistent state bijhoudt in een database. Kun je bij een fout niet gewoon het stuk code wat de requests afhandelt opnieuw initialiseren? Waarom zou de hele application server dan down gaan?

Wat ik me wel kan voorstellen is dat een application server herstart moet worden als er door een fout zoveel geheugen gealloceerd is (en niet makkelijk kan worden vrijgegeven) dat de andere request afhandelingen out of memory exceptions gaan geven, of dat 1 van je threads in een oneindige loop zit en er geen mechanisme via de server is om deze netjes te killen.

In C++ en een threaded omgeving is het overigens wel zo dat een fout in een willekeurige thread het hele systeem plat ligt, maar ik java kan dat niet. Tenzij het een VM error is (die nog steeds blijven voorkomen in alle versies van de VM die ik ken)

Het is natuurlijk wel zo dat als je code wilt gaan aanpassen er wel een herstart van je server nodig is. Maar hele weinig ondersteunen hotcode swap in andere dingen dan jsp pagina's.

Wat ik nog minder snap is waarom je zou moeten redeployen. Een runtime error kan toch niet je .war or .ear beschadigen? Of heb je code die naar je eigen jsp's of class files schrijft?
M.a.w.: zodra het wat complexer wordt dan actie-reactie (zoals HTTP)
Niet voor het een of ander maar http gebasseerde systemen kunnen ook aardig complex zijn, neem nu bijvoorbeeld het struts framewok zelf. Je hebt in zulke systemen alleen zelden data die geshared wordt door verschillende users, anders dan via de DB.

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


Verwijderd

Voor het pakket waar ik nu aan werk (erp pakket) wordt er (zoals B-Man ook aandraagt) bij vervelende Exceptions een emailtje gestuurd naar de systeembeheerder. De systeembeheerder kan vervolgens via een JMX-console het probleem-component evt. uit- en weer inschakelen.

Het probleem met het 'gewoon' opnieuw opstarten van de server (en automagisch redeployen) is dat het systeem ondertussen down is en er gebruikers niet kunnen werken.

Het ligt gewoon helemaal aan de situatie "at-hand" en hoe je daar mee om kunt gaan. Is het een groot bedrijf, klein bedrijfje. Heb je afspraken over uptime etc. Wij hebben bijvoorbeeld een SLA'tje waarin een bepaalde uptime wordt gegarandeerd.
Pagina: 1