C-uppsats
LITH-ITN-EX--05/010--SE
System för registrering av
underhållsjour
Fredrik Johansson
Peter Lindvall
2005-05-20
LITH-ITN-EX--05/010--SE
System för registrering av
underhållsjour
Examensarbete utfört i Datorteknik
vid Linköpings Tekniska Högskola, Campus
Norrköping
Fredrik Johansson
Peter Lindvall
Handledare Rickard Klingberg
Examinator Kenneth Bjerner
Rapporttyp Report category Examensarbete B-uppsats C-uppsats D-uppsats _ ________________ Språk Language Svenska/Swedish Engelska/English _ ________________ Titel Title Författare Author Sammanfattning Abstract
ISBN
_____________________________________________________
ISRN
_________________________________________________________________Serietitel och serienummer
ISSN
Title of series, numbering ___________________________________
Nyckelord
Keyword
Datum
Date
URL för elektronisk version
Avdelning, Institution
Division, Department
Institutionen för teknik och naturvetenskap
Department of Science and Technology
2005-05-20
x
x
LITH-ITN-EX--05/010--SE
http://www.ep.liu.se/exjobb/itn/2005/de/010/
System för registrering av underhållsjour
Fredrik Johansson, Peter Lindvall
På Bravikens pappersbruk tillämpas idag ej skiftgående underhåll, istället används en underhållsjour
som kallas ut vid problem. T.ex. om en motor havererat. I dagsläget sker en del av denna registrering på
papper, vilket medför att hanteringen blir tidsödande och ineffektiv. I det här examensarbetet har vi
utvecklat ett program som ska underlätta för vakten att registrera dessa jourtillfällen.
Programspråket Java valdes för att utveckla programmet eftersom det går att skriva applikationer som är
direkt körbara från en webbläsare – sk. applets. Alla på intranätet kan då komma åt programmet.
Nackdelen med applets är att den har väldigt begränsade rättigheter. De får t.ex. inte öppna en socket (en
anslutning) till en annan dator. Detta orsakar problem eftersom appleten och databaserna ligger på skilda
servrar. Problemet löstes genom att installera ett ”vidarbefordringsprogram” på samma server som
appleten. Eftersom appleten får ansluta till samma server den är sparad på, kan anslutningen ske till detta
program istället som i sin tur ansluter till databaserna.
Vi använder databasgränsnittet JDBC för all kommunikation med databaserna. Programmet hämtar
information från en databas och lagrar den i en annan. Ett annat önskemål var att programmet skulle ha
flera fönster öppna samtidigt. Eftersom programmet körs från en webbläsare tyckte vi att det var bättre
att använda sig av flikar. Detta gör att det blir mindre rörigt, och lättare för användaren att navigera
mellan jourtillfällena.
Upphovsrätt
Detta dokument hålls tillgängligt på Internet – eller dess framtida ersättare –
under en längre tid från publiceringsdatum under förutsättning att inga
extra-ordinära omständigheter uppstår.
Tillgång till dokumentet innebär tillstånd för var och en att läsa, ladda ner,
skriva ut enstaka kopior för enskilt bruk och att använda det oförändrat för
ickekommersiell forskning och för undervisning. Överföring av upphovsrätten
vid en senare tidpunkt kan inte upphäva detta tillstånd. All annan användning av
dokumentet kräver upphovsmannens medgivande. För att garantera äktheten,
säkerheten och tillgängligheten finns det lösningar av teknisk och administrativ
art.
Upphovsmannens ideella rätt innefattar rätt att bli nämnd som upphovsman i
den omfattning som god sed kräver vid användning av dokumentet på ovan
beskrivna sätt samt skydd mot att dokumentet ändras eller presenteras i sådan
form eller i sådant sammanhang som är kränkande för upphovsmannens litterära
eller konstnärliga anseende eller egenart.
För ytterligare information om Linköping University Electronic Press se
förlagets hemsida
http://www.ep.liu.se/
Copyright
The publishers will keep this document online on the Internet - or its possible
replacement - for a considerable time from the date of publication barring
exceptional circumstances.
The online availability of the document implies a permanent permission for
anyone to read, to download, to print out single copies for your own use and to
use it unchanged for any non-commercial research and educational purpose.
Subsequent transfers of copyright cannot revoke this permission. All other uses
of the document are conditional on the consent of the copyright owner. The
publisher has taken technical and administrative measures to assure authenticity,
security and accessibility.
According to intellectual property law the author has the right to be
mentioned when his/her work is accessed as described above and to be protected
against infringement.
For additional information about the Linköping University Electronic Press
and its procedures for publication and for assurance of document integrity,
Sammanfattning
På Bravikens pappersbruk tillämpas idag ej skiftgående underhåll, istället används en
underhållsjour som kallas ut vid problem. T.ex. om en motor havererat. I dagsläget sker en del
av denna registrering på papper, vilket medför att hanteringen blir tidsödande och ineffektiv. I
det här examensarbetet har vi utvecklat ett program som ska underlätta för vakten att
registrera dessa jourtillfällen.
Programspråket Java valdes för att utveckla programmet eftersom det går att skriva
applikationer som är direkt körbara från en webbläsare – sk. applets. Alla på intranätet kan då
komma åt programmet. Nackdelen med applets är att den har väldigt begränsade rättigheter.
De får t.ex. inte öppna en socket (en anslutning) till en annan dator. Detta orsakar problem
eftersom appleten och databaserna ligger på skilda servrar. Problemet löstes genom att
installera ett ”vidarbefordringsprogram” på samma server som appleten. Eftersom appleten får
ansluta till samma server den är sparad på, kan anslutningen ske till detta program istället som
i sin tur ansluter till databaserna.
Vi använder databasgränsnittet JDBC för all kommunikation med databaserna. Programmet
hämtar information från en databas och lagrar den i en annan. Ett annat önskemål var att
programmet skulle ha flera fönster öppna samtidigt. Eftersom programmet körs från en
webbläsare tyckte vi att det var bättre att använda sig av flikar. Detta gör att det blir mindre
rörigt, och lättare för användaren att navigera mellan jourtillfällena.
Abstract
At the Braviken paper mill a non-shiftworking maintenance is applied today. Instead they use
a maintenance duty group which is called in for example if an engine has broken down. Today
a part of this registration is on paper which makes the handling time consuming and
inefficient. In this thesis we have developed a program which will make it easier for the guard
to register these duty occasions.
The program language Java was chosen to develop the program, as you can write applications
which are directly applicable from a webreader so-called applets. Then everybody with
intranet can reach the program. The disadvantage with applets is that it has got very limited
rights. Thery must not for example open a socket (a connection) to another computer.This
causes problems as the applet and the database are on different servers. The problem is solved
by installing a forwarding program on the same server as the applet. As the applet is allowed
to connect to the same server on which it is saved, the connection can be done to this program
instead which then connects to the databases.
We use the database limit JDBC for all communication with the databases. The program gets
information from one database and stores it in another one. Another desire was that the
program should be able to have more windows open at the same time. As the program is
driven from a webreader, we thought it was better to use flaps. That makes it less complicated
and easier for the user to navigate between the duty occasions.
Förord
Det har varit ett väldigt lärorikt examensarbete på Bravikens pappersbruk. Under vår studietid
har vi endast gjort mindre projekt, som varit relativt begränsade. Naturligtvis kan vi inte allt
från början, men har nu sett att vi har kunskaper nog för att läsa in helt nya områden och
förstå dem. Visst har det funnits problem, men inga så stora att de varit oöverkomliga, även
om det sett mörkt ut ibland. Utan dessa problem hade dock arbetet känns ganska platt, och
varit trist att utföra. Det är trots allt misstagen man lär sig av.
Vi vill tacka Bravikens pappersbruk för att vi fick möjlighet att göra vårt examensarbete hos
Er. Ett speciellt tack till Rickard Klingberg för din goda handledning och stora engagemang.
Tack även till Gösta Nilsson och Jan Rask för att Ni ställt upp när vi har haft problem med vår
databas.
Examensarbetet har gett oss en liten inblick i hur ett framtida jobb skulle kunna se ut.
Förhoppningsvis har vi även skapat nya kontakter som vi kan dra nytta av senare.
Peter Lindvall
Fredrik Johansson
Innehållsförteckning
1
INLEDNING... 1
1.1
P
ROBLEMSTÄLLNING... 1
1.2
S
YFTE... 1
1.3
O
MFATTNING... 1
1.4
B
RAVIKENS PAPPERSBRUK... 1
1.5
R
APPORTENS STRUKTUR... 2
2
JOURSYSTEMET ... 3
2.1
B
AKGRUND... 3
2.1.1
Hanteringen idag ... 3
2.1.2
Hanteringen imorgon ... 3
2.1.3
Val av programspråk... 3
2.1.4
Java ... 4
2.1.5
JApplet kontra JFrame... 4
2.1.6
Databasgränssnitt ... 5
2.2
S
ÄKERHETEN I ENA
PPLET... 6
2.2.1
Signerad Applet... 6
2.2.2
Oracle Connection Manager... 7
2.3
K
ONFIGURATION AVO
RACLEC
ONNECTIONM
ANAGER... 8
2.4
J
OURDATABASEN... 8
2.5
P
ROGRAMMERING... 10
2.5.1
Förarbete och brainstorming ... 10
2.5.2
Egna klasser... 10
2.5.3
Databaskonstruktion ... 13
2.5.4
Konvertering till Applet... 14
2.5.5
Design ... 15
2.5.6
Flikhantering... 18
2.5.7
Test och justeringar... 20
3
RESULTAT ... 22
3.1
S
LUTSATSER... 22
3.2
R
EKOMMENDATIONER FÖR FORTSATT ARBETE... 22
4
REFERENSLISTA... 23
4.1
T
RYCKTA KÄLLOR... 23
4.2
E
LEKTRONISKA KÄLLOR... 23
5
BILAGOR ... 24
5.1
K
ONFIGURATION AVO
RACLEC
ONNECTIONM
ANAGER... 24
5.1.1
cman.ora ... 24
5.1.2
tnsnames.ora ... 24
5.1.3
Installationsanvisning i Windows... 25
5.2
I
NSTALLATIONSANVISNING FÖR APPLET... 25
5.2.1
Färdigställande av applet ... 25
5.2.2
Installation på wxebbserver ... 26
5.3
P
ROGRAMKOD... 27
5.3.1
JourApplet.java ... 27
5.3.2
RapportApplet.java ... 43
5.4
E
GNA KLASSER... 61
5.4.1
DBControl.java ... 61
5.4.2
TimeDateControl.java... 65
5.4.3
JTableControl.java... 67
Figur- & tabellförteckning
F
IG.
1:
F
RÅNSQLJ
TILL KÖRBART PROGRAM. ... 5
F
IG.
2:
S
IGNERAD APPLET. ... 6
F
IG.
3:
C
ONNECTIONM
ANAGER... 7
F
IG.
4:
S
Å HÄR FUNGERAR VYN... 8
F
IG.
5:
V
AD SOM HÄMTAS FRÅNIFS
NÄR ETT ARBETSORDERNUMMER SKRIVS IN... 9
F
IG.
6:
E
XEMPEL PÅ HUR JOURTABELLERNA RELATERAR TILL VARANDRA. ... 9
F
IG.
7:
UML-
DIAGRAM ÖVER PROGRAMMETS KLASSER... 12
F
IG.
8:
G
RÄNSSNITT1
(S
TARTSIDAN) ... 15
F
IG.
9:
G
RÄNSSNITT1
MED EXEMPEL PÅ EN COMBOBOX... 15
F
IG.
10:
G
RÄNSSNITT2 ... 16
F
IG.
11:
I
NMATNING AV ANSTÄLLNINGSNUMMER UTAN ATT TRYCKA ENTER... 16
F
IG.
12:
E
FTER ENTERSLAG FYLLS DE ÖVRIGA FÄLTEN I AUTOMATISKT... 16
F
IG.
13:
I
NMATNING AV ARBETSORDERNUMMER UTAN ATT TRYCKA ENTER... 17
F
IG.
14:
E
FTER ENTERSLAG FYLLS DE ÖVRIGA FÄLTEN I AUTOMATISKT... 17
1 Inledning
1.1 Problemställning
De problemställningar en programmerare allmänt ställs inför är inte alltid lätta att förutse, allt
eftersom arbetet fortskridit har nya problem dykt upp. Nedanstående lista visar vilka
funderingar som fanns innan examensarbetet startade.
• Vilket programspråk är lämpligast att utveckla i?
• Vilken databaslösning skall användas?
• Hur sker kommunikationen mot den interna databasen?
• Hur skall användargränssnittet se ut?
• Hur skall jourdatabasen utformas?
• Hur skall programmet skrivas för att vara lättåtkomligt av alla?
1.2 Syfte
På Bravikens pappersbruk tillämpas idag ej skiftgående underhåll, istället används en
underhållsjour som kallas ut vid problem. Planering och avrapportering sker idag helt
manuellt, och en Word-fil på intranätet visar vem som har jouren.
Vår uppgift är att utveckla ett nytt system för att underlätta registreringen av underhållsjouren.
Systemet skall göra det lättare att t.ex. föra statistik, samt underlätta den för tillfället krångliga
hanteringen.
1.3 Omfattning
Det här examensarbetet omfattar 10 veckor, dvs. 10 poäng, och är en del av en
högskoleingenjörsexamen i Data- och Elektroteknik. Vi har utvecklat ett program åt
Bravikens pappersbruk för att på ett enklare och effektivare sätt registrera deras
underhållsjour. Ca sju veckor har avsatts åt utveckling och de resterande tre åtgår till små
justeringar i programmet och rapportskrivning.
1.4 Bravikens pappersbruk
Bravikens pappersbruk ligger utanför Norrköping vid Bråvikens början. Braviken invigdes
1977, och med sina tre pappersmaskiner har de slagit det ena världsrekordet efter det andra.
Produktionskapaciteten är 700.000 ton papper per år och företaget har drygt 700 anställda.
Bravikens pappersbruk tillverkar vitt och färgat papper. T.ex. det rosa papper Aftonbladets
sportbilaga är tryckt på. Huvuddelen av Bravikens produktion säljs på export, endast 10%
stannar i Sverige.
Braviken är ett av fyra bruk i Holmen-koncernen. De övriga är Vargön, Madrid och
Halstavik.
1.5 Rapportens struktur
Rapporten är uppdelad i fyra delar vilka beskrivs kort nedan.
Kap. 1 : Inledning
Den här delen behandlar bakgrunden till varför detta arbete utförts, vilka problemställningar
som fanns samt en kort presentation av företaget.
Kap. 2 : Joursystemet
Detta är rapportens huvuddel. Den börjar med lite inledande teori, och avslutas med en
detaljerad redogörelse av utvecklingsarbetet och de problem som uppkommit.
Kap. 3 : Resultat
Här presenteras vad vi kommit fram till och vilka slutsatser som gjorts. Avsnittet slutar med
förslag på vidareutveckling av programmet.
2 Joursystemet
2.1 Bakgrund
2.1.1 Hanteringen idag
Bravikens pappersmaskiner är i drift dygnet runt. På dagtid finns det alltid personal på plats
som kan rycka ut om något går sönder. På natten däremot, jobbar endast skiftlaget. Om något
skulle hända då måste en arbetsorder utfärdas av en processingenjör. Arbetsordern är en
specifikation på vad som har hänt och åtgärder som skall utföras. En motor kan t.ex. haverera,
och behöver i så fall bytas snarast. Arbetsordern skickas sedan till vakten. Vakten i sin tur
ringer ut behövd personal, i det här fallet t.ex. en elektriker och en mekaniker. Jourhavande
vakt registrerar när personalen ankommer och går hem. Detta görs direkt i Bravikens
underhållssystem (IFS).
Skulle det bli fel i inmatningen finns det inget sätt att radera misstaget. Istället skrivs en
”inverterad” rad som tar ut den felaktiga. Om det t.ex. blivit åtta timmar av misstag, måste det
korrigeras med en ny rad där det står minus åtta timmar. Denna hantering är omständlig, och
medför att listorna kan bli väldigt plottriga. Registrering av jourtillfälle skickas från vakten,
på papper, till personalavdelningen som skriver in uppgifterna i lönesystemet.
2.1.2 Hanteringen imorgon
Meningen med programmet är att det inte ska behövas någon onödig hantering av papper.
Vakten får precis som förut en arbetsorder, men istället för att sätta den i en pärm för
vidarebefordran, skapar vakten ett nytt jourtillfälle där uppgifterna förs in. På så sätt finns alla
uppgifterna på ett ställe och är tillgängligt för alla parter, eftersom programmet är åtkomligt
från intranätet. Det blir t.ex. lättare för personalen att följa upp sitt eget arbete. Det underlättar
även för sektions- och gruppcheferna att se vilken personal som varit ute under natten, och
vilka åtgärder som utförts. Inom en snar framtid är det även tänkt att lönekontoret skall ta sina
uppgifter direkt från programmet. Andra fördelar med programmet är att det är överskådligt
och lätt att använda. Funktioner som att radera en felaktig rad är nu inte längre omöjligt.
2.1.3 Val av programspråk
Enligt önskemål skall programmet kunna köras i en webbläsare, vilket skulle underlätta då
installation inte behövs. JSP (Java Server Pages), C# och Java är tre programspråk som kan
användas för att lösa uppgiften.
JSP är bra för att det är ett serverbaserat språk och kan användas oberoende av webbläsare.
Det som är mindre bra är att det inte går att skapa ett bra gränssnitt på ett lätt sätt. Språket är
beroende av HTML (Hypertext Markup Language) och CSS (Cascading StyleSheets) för att
bygga designen. Detta är absolut inte det bästa eller lättaste sättet att bygga upp gränssnittet
på.
C# är ett stabilt och snabbt språk som kan användas för att skapa t.ex. webservices. Det är ett
sätt att exekvera programkod direkt i en webbläsare. Koden körs då via Microsofts .NET
Framework. Eftersom det inte var säkert att Microsoft .NET Framework var installerat på alla
företagets datorer, och p.g.a. att vår kontakt med språket är relativt liten, blev detta inte vårt
val.
Java använder sig av en VM (Virtual Machine) från antingen Sun eller Microsoft. Alla
Bravikens datorer har som standard en VM installerad, vilket är ett väldigt starkt argument för
att välja Java. I vår utbildning har vi dessutom använt detta språk frekvent, och därför blev
detta vårt val.
2.1.4 Java
Java är ett programspråk som utvecklats av Sun Microsystems. Det släpptes 1995 och bygger
på programspråket C++. Språkets första användningsområde var som små applikationer
(applets) som användes för att ge liv åt hemsidor. Det kunde t.ex. handla om små spel och
animationer. Java är dock så mycket mer än så. Det är ett fullvuxet programspråk, som kan
användas för att skapa liknande applikationer som t.ex. i C++.
Det som gör Java speciellt intressant är:
• Java är plattformsoberoende, vilket betyder att det inte spelar någon roll vilket
operativsystem användaren kör. Programmet är alltså körbart oavsett datorsystem.
• Java har utmärkta funktioner för att skapa grafiska användargränssnitt. Även de är
plattformsberoende, och kommer att se likadana ut på alla datorsystem.
• Java är ett objektorienterat språk. Alla variabler är samverkande objekt som beskrivs
av klasser.
• Java stöder trådar (threads) som möjliggör att programmet kan utföra flera saker
samtidigt. T.ex. mata in text samtidigt som en rörlig bild visas.
Detta var fördelarna, men precis som med alla andra språk har Java även nackdelar. Den
största nackdelen är prestandan, exekveringen sker betydligt långsammare än t.ex. C++.
Anledningen till detta är att Java interpreteras i realtid vid programkörning, medan t.ex. C++
gör om koden till maskinkod redan vid kompileringen.
2.1.5 JApplet kontra JFrame
JApplet och JFrame är två Swing-klasser i Java som används för att bygga grafiska
användargränssnitt.
JFrame är ett vanligt programfönster och fungerar precis som vilket annat windows-program
som helst. Allt som går att göra i ett vanligt program kan även göras här, t.ex. radera eller
skapa filer på den lokala hårddisken.
JApplet har till skillnad från en JFrame ingen egen fönsterhanterare. Poängen med en applet
är att den skall köras i din webbläsare. På så sätt kommer programmet att vara tillgängligt
oavsett var du befinner dig, bara det finns en internetuppkoppling.
Skriv ditt SQLJ-program Översätt och kompilera Kör programmet .sql .class
Det finns egentligen bara tre väsentliga skillnader mellan en JApplet och en JFrame.
• Den klass
1man konstruerar skall vara en subklass till JApplet istället för JFrame.
• Konstruktorn
2ersätts mot en init-funktion.
• Det behövs ingen metod med namnet main
3.
2.1.6 Databasgränssnitt
Java och en databas, av valfri sort, pratar inte samma språk. Det kan jämföras med att en
svensk och en tysk pratar med varandra på respektive modersmål. Ingen av parterna kommer
att förstå varandra. Det behövs alltså en tolk.
Precis på samma sätt behöver Java en tolk för att kunna prata med databasen. JDBC och
SQLJ är de två största databasgränssnitten för Java. Vilken lämpar sig då bäst för uppgiften?
JDBC (Java Database Connectivity) är ett API (programmeringsgränssnitt) för att
kommunicera med en databas med hjälp av Java. Förutom API:n består JDBC även av en
drivrutin. Denna arkitektur innebär att utformningen av javaprogrammet blir den samma
oavsett vilken databas som anropas. Ett byte av databasserver innebär endast ett byte av
drivrutin för att det skall fungera igen. Denna lösning kan därför betraktas som plattforms-
och produktoberoende.
SQLJ är en ny standard för att skriva SQL-frågor direkt i Java. Det är en öppen standard som
utvecklats bl.a. av Oracle och IBM. I SQLJ är det enklare att skriva komplicerade SQL satser.
Detta för att programmeraren enklare kan använda sig av egna variabler i SQL-frågan.
Fig. 1: Från SQLJ till körbart program.
JDBC har inget sätt att kontrollera om SQL-frågan blivit korrekt ställd. SQLJ däremot, har en
inbyggd felkontroll. Koden måste nämligen kompileras för att översätta SQL till Java innan
det går att kompilera själva programmet. Därför hittas alla SQL-fel under kompileringen
istället för vid programkörning, som sker med JDBC.
SQLJ körs ovanpå JDBC, vilket innebär att JDBC måste implementeras innan SQLJ kan
användas. Det betyder att två standarder måste läras in istället för en. Behovet av avancerande
SQL-satser är i detta fall minimalt, därför blev JDBC det givna valet.
1
En beskrivning av hur ett objekt ser ut och beter sig kallas klass
2Den metod som anropas varje gång det skapas ett objekt av klassen.
3Den fösta metod som alltid anropas när ett program av typen JFrame körs.
Applet
³
Signerad Applet
2.2 Säkerheten i en Applet
Att det skulle finnas begränsningar i vad en applet får och inte får göra, var inget som någon
av oss hade en tanke på. Själva idén med att utveckla en applet blev därför inte lika lätt som
förväntat. Det visade sig att en applet inte får göra allt som en applikation får göra. En
applikation har full tillgång till datorn och filsystemet, dvs. det går t.ex. bra att skapa eller ta
bort en fil. Den får även öppna en socket till valfri dator. En applet däremot, kan bara öppna
en socket mot den server den är hämtad från. Den har heller ingen access till det lokala
filsystemet.
Dessa restriktioner finns på grund av att en applet är ett körbart program som kan kommas åt
av alla, eftersom den ligger på en webbserver och inte kräver någon installation. Det räcker
med att användaren surfar in på webbsida för att det skall vara för sent. Om inte dessa
restriktioner fanns skulle appleten enkelt kunna göra mer skada än nytta.
Detta vållade ett stort problem, ty appleten skall vara lättåtkomlig för alla, men samtidigt
kunna ansluta till en annan dator. Efter några dagars forskande uppenbarade sig två lösningar
på problemet – Signerad Applet och Connection Manager.
2.2.1 Signerad Applet
Ett sätt att helt släppa på de restriktioner som finns är att signera sin applet. Den får då samma
rättigheter som en vanlig applikation. Det första som måste göras är att skapa ett certifikat.
Vid skapandet skall du mata in namn, adress, företagsnamn, och land. Meningen med ett
certifikat är att du som utvecklare intygar att innehållet i appleten är säkert, och inte bringar
någon skada. Eftersom du går i god för programmet, släpps alla säkerhetsrestriktioner.
Problemet är att det inte finns någon kontroll på att ditt certifikat är äkta, d.v.s. innehåller
sanningsenliga uppgifter. Det går jättebra att hitta på alla uppgifter i certifikatet, och på så sätt
slippa allt ansvar. Därför finns det företag som går emellan och intygar att uppgifterna i
certifikatet är riktiga. Företagen tar dock ofta, för att inte säga alltid, ut en rejäl summa pengar
för den här tjänsten.
När certifikatet är skapat skall det kopplas till en applet för att fungera. Varje gång en
användare sedan surfar in på webbsidan får han en fråga om appleten får köras. Om han
godkänner kommer appleten att köras med full access. Detta kan vara riskabelt om inte
användaren vet vem som egentligen signerat appleten.
Databas
Connection
Manager
Applet
Dator ett
Dator två
Fördelen med den här metoden är att appleten får precis alla spärrar hävda, dvs. full access.
Det här är också den enda fördelen. Nackdelarna är desto fler. Till och börja med finns det
ingen standard för hur en applet skall signeras. Processen är beroende av vilken webbläsare
som används, och även vilken version av javatolken som är installerad. Signaturerna är inte
heller kompatibla med varandra.
Under projektets gång testades ett dussin olika sätt att signera appleten. Inget fungerade. Med
tanke på att det saknas en standard för hur signering skall gå till, är metoden ganska värdelös
och ger därför ingen lösning på problemet.
2.2.2 Oracle Connection Manager
En connection manager (hädanefter CM) fungerar ungefär som en router
4. Det är alltså
möjligt att ansluta till den, och via den ansluta till en annan server. Om t.ex. CM är installerad
på samma server som appleten undviks problemet med att det inte går att skapa sockets till
andra datorer. Appleten ansluter alltså till CM som i sin tur skapar anslutningen till den andra
maskinen.
Fördelarna med det här tillvägagångssättet är att ingen hänsyn behöver tas till vare sig
javatolk eller webbläsare. Appletens säkerhetsrestriktioner finns fortfarande kvar, så
användaren behöver inte vara orolig att något skall hända med dennes dator. Det blir ingen
krånglig hantering med t.ex. certifikat. Användaren kommer inte ens att märka av att CM
arbetar i bakgrunden, appleten beter sig precis som vanligt.
Nackdelarna är att anslutningssyntaxen i koden blir lite annorlunda, jämfört med att ansluta
direkt till den andra datorn. Om appleten avslutats utan att anslutningen stängts på ett riktigt
sätt, kommer anslutningen i CM att ligga kvar och låsa upp processen. Detta medför att CM
måste startas om för att fungera igen. Därför bör programmeraren skriva koden så att
anslutningarna till CM alltid stängs oavsett hur appleten avslutas.
I och med att CM uppfyller allt som behövs blev detta lösningen på problemet.
Fig. 3: Connection Manager
Applet
Databasvy
A_vy B_vy
Databas
A B
2.3 Konfiguration av Oracle Connection Manager
I filen cman.ora ställs lyssnaren in. Där specificeras vilken ip- och port-adress CM skall
lyssna på.
cman = (ADDRESS_LIST=
(ADDRESS=(PROTOCOL=tcp)(HOST=lyssnarip)(PORT=1630)) )
cman_admin = (ADDRESS=(PROTOCOL=tcp)(HOST=lyssnarip)(PORT=1830))
Lyssnaren ställs in för att datorn skall känna av när ett program försöker ansluta till managern.
I konfigureringsfilen tnsnames.ora anges alla hopp som CM skall kunna göra. Med hopp
menas vilken server CM skall omdirigera trafiken till.
CMAN_IFS.WORLD = (DESCRIPTION = (ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = lyssnarip)(PORT = 1630)) (ADDRESS = (PROTOCOL = TCP)(HOST = databasip)(PORT = 1521)) ) (SOURCE_ROUTE = yes) (CONNECT_DATA = (SERVICE_NAME = pumaprod) ) )
Första adressraden anger vilken port och ip som Connection Managern skall lyssna på. Andra
raden i adresslistan anger vilken adress den skall ansluta till. För varje ny server som skall
läggas till, måste en liknande konfiguration göras i tnsnames.ora.
Managern startas med kommandot cmctl start och ligger därefter som en process på servern.
För att testa om Connection Managern fungerar som den ska kan kommandot tnsping
användas. För att testa ovanstående omdirigering ges kommandot: tnsping cman_ifs. Om allt
fungerar som det ska, skall ett svar från ”HOST = databasip” returneras.
2.4 Jourdatabasen
Bravikens pappersbruk använder Oracles databassystem som koncernstandard. I och med det
användes även Oracles system när jourdatabasen skulle skapas. Data till jourdatabasen hämtas
från IFS. Det är ett relativt nytt system, vilket gör att databasens design fortfarande kan
komma att ändras. Därför skapades s.k. vyer som fungerar som ett mellanled mellan
databasen och programmet. Kolumnerna i vyerna är kopplade till databasens kolumner. Om
en kolumn i databasen ändras, behöver den bara pekas om i vyn och inte ändras i koden.
IFS-databasen används för att hämta personal- och arbetsorderdata till programmet. Detta
görs dels för att kontrollera om användaren fyllt i rätt uppgifter och dels för att undgå att
behöva skriva sådant som redan finns i systemet. T.ex. hämtas all relevant data om en
arbetsorder så fort ett giltigt arbetsordernummer matas in.
Fig. 5: Vad som hämtas från IFS när ett arbetsordernummer skrivs in.
Jourdatabasen består av tre tabeller – jourid, jourpersonal och jourorder. Den första tabellen
innehåller alla skapade jourtillfällen, de åtskiljs genom ett unikt id-nummer. Id-numret räknas
upp automatiskt när ett nytt jourtillfälle skapas. Jourpersonal och jourorder innehåller den
personal och de arbetsordrar som tillhör respektive jourtillfälle. I dessa två tabeller är inte
id-numret unikt, t.ex. om ett jourtillfälle har flera arbetsordrar, har de också samma id-nummer.
På detta sätt är det lätt att plocka ut vilka ordrar och vilken personal som hör till respektive
jourtillfälle.
Jourid
Id Datum
Tid
1 2005-04-18
22:14
2 …
…
Jourpersonal
Id Namn
Arbetstid
1 Kalle
Karlsson
08:00
1 Sven
Svensson
03:30
2 Anna
Andersson 04:00
Jourorder
Id AO.nr.
Arbetsbeskrivning
1
324654
Byte av vals
1
554878
Byte av motor
1 426587
Korrigering
av
inloppslåda
2 365533
…
2 125546
…
Fig. 6: Exempel på hur jourtabellerna relaterar till varandra.
I exemplet ovan är det lätt att se vilka rader i tabellerna som hör ihop. Det går t.ex. att utläsa
att det skapades ett jourtillfälle den 18 april 2005 klockan 22:14. Kalle Karlsson och Sven
Svensson kallades ut och utförde arbetsordrarna 324654, 554878 och 426587. Observera att
tabellerna är ofullständiga, och bara är till för att tydliggöra hur relationerna fungerar.
2.5 Programmering
Detta avsnitt behandlar arbetsgången från idé till färdig produkt. Läsaren kommer att guidas
genom hela utvecklingsarbetet med mer detaljerade beskrivningar av eventuella problem och
lösningar.
2.5.1 Förarbete och brainstorming
Den fråga som först dök upp var på vilket sätt programmet skall skrivas för att på ett så enkelt
sätt som möjligt kunna användas av alla. Vi kom snabbt överens om att ett webbgränsnitt var
den bästa lösningen. Javas fördelar övervägde och lösningen med att skriva en applet medför
att programmet blir lättåtkomligt utan krångliga installationer.
Från början önskades det att varje jourtillfälle skulle ha ett eget fönster, och flera fönster
skulle kunna vara öppna samtidigt. Det kanske inte var den bästa lösningen. Istället funderade
vi på att använda oss av flikar. Detta gör att det endast behövs ett fönster, samt att det blir
lättare att organisera de olika jourtillfällena.
2.5.2 Egna klasser
Programmet är till största del uppbyggt av tabeller i olika storlekar. All information, som inte
matas in manuellt, hämtas från databaser. Det skall finnas bra hantering för datum och tid,
med möjlighet att beräkna tidsskillnader som sträcker sig över datumgränsen. Med detta i
åtanke skapades tre klasser för dessa ändamål.
JTableControl.java
Klassen används för att kontrollera och styra allt som har med tabeller att göra. Den ser ut på
följande sätt.
Instansvariabler
DefaultTableModel model Tabellmodell. JTable t Tabell. JScrollPane sp Rullningslist.int nrColumns Håller reda på hur många kolumner en tabell innehåller. boolean COL_SELECT Bestämmer markeringsläge.
boolean ROW_SELECT Bestämmer markeringsläge.
boolean REORDER Anger om tabellens kolumner får byta plats med varandra eller inte.
Instansmetoder
JTableControl(boolean editable) Konstruktor. Skapar ett nytt tabellobjekt. Editable sätts till true om tabellen inte skall vara editerbar.getTableInScrollpane() Returnerar tabellen i en rullningslist.
getTable() Returnerar tabellen. getTableModel() Returnerar tabellens modell.
GetCellValue(int row, int col) Returnerar värdet på cellposition (rad, kolumn). setSizeOfTable(int x, int y) Bestämmer tabellens storlek i pixlar. setColumnNames(String[] s) Sätter kolumnnamn via en bifogad strängarray. AppendRow(Object[] o) Lägger till en rad sist i tabellen. deleteRow(int rowNr) Tar bort rad på position rowNr. deleteAllRows() Tar bort alla rader från tabellen.
addEmptyRow(int n) Lägger till n stycken tomma rader i tabellen. addComboToColumn(int nrCols, String[] s)
Ändrar kolumnens inmatningsläge till valbar lista. Variablen nrCols bestämmer i vilken kolumn ändringen skall ske, s innehåller de val som skall gå att göra.
getSelRow() Returnerar den markerade radens index. getSelColumn() Returnerar den markerade kolumnens index. setColumnWidth(int c, int width) Bestämmer kolumnbredd.
TimeDateControl.java
Det finns även en del tidsberäkningar som behöver göras. När ett jourtillfälle skapas ska
programmet automatiskt registrera aktuellt datum och tid. Det ska även gå att beräkna
tidsskillnaden mellan två tider, oavsett om de överskrider datumgränsen. T.ex. beräkna tiden
mellan 22.10 idag till 01.10 imorgon. För att lösa detta beräknas tiden från tillfälle ett till
tillfälle två i millisekunder. Sedan omvandlas den totala tiden till timmar och minuter.
public String calcDifference(TimeDateControl dtc) {
long diffMillis = dtc.c.getTimeInMillis()-this.c.getTimeInMillis(); long diffMins = (diffMillis/(60*1000))+(dtc.hour*60+dtc.min)- (this.hour*60+this.min);
long diffHours = diffMins/60; diffMins = diffMins%60;
return timeFormat((int)diffHours,(int)diffMins); }
Variabeln diffMillis lagrar skillnaden mellan datumen i tillfälle ett och två, och sparar det
svaret som millisekunder. Sedan omvandlas diffMillis till minuter i diffMins, där tas även
hänsyn till den aktuella tiden på respektive tillfälle. Antalet timmar och minuter returneras
genom funktionen timeFormat, som ger tiden rätt form. Åtta timmar och 2 minuter blir
”08:02” istället för ”8:2”.
Instansvariabler
Calendar c Kalenderobjekt int year Årint month Månad int day Dag int hour Timme int min Minut
Instansmetoder
TimeDateControl() Dafaultkonstruktor. Skapar ett tidsobjekt med aktuell tid och datum. TimeDateControl(int h, int m)Konstruktor. Skapar ett tidsobjekt där variablerna h sätter timmarna och m sätter minuterna.
TimeDateControl(String timestamp)
Konstruktor. Skapar ett tidsobjekt med valbar datum och tid, genom att skicka med en timestamp: ”YYYY-MM-DD, HH:MM”. timeFormat(int h,int m) Justerar tidsformat från t.ex. 8:3 till 08:03. getTime() Returnerar aktuell tid.
getDate() Returnerar aktuellt datum. getYesterday() Returnerar gårdagens datum.
calcDifference(TimeDateControl dtc) Beräknar tidsskillnaden mellan två tidsobjekt. isAnkAfterKlar(TimeDateControl dtc) Returnerar true om ankomsttid är före klartid.
Jourapplet DBControl TimeDateControl JTableControl JApplet ActionListener TableChangeListener
Den sista klassen hanterar allt som har med databaser och anslutningar att göra. Klassen
innehåller funktioner som att ansluta till, ställa frågor och infoga data i databasen.
Funktionerna är samlade i filen DBControl.java.
Instansvariabler
Statement s Behövs för att ställa frågor till databasen. Connection c Behövs för att skapa en anslutning. ResultSet rs Svaren från databasen sparas här. String DB_ADR_LISTEN Connection Managerns adress. String DB_PORT_LISTEN Connection Managerns portnr. String DB_ADR Databasens adress.String DB_PORT Databasens portnr. String DB_SID Databasens SID. String USER Användarnamn. String PASS Lösenord.
Instansmetoder
DBControl(String dba, String dbp, String dbi, String u, String p)
Konstruktor. Skapar ett databasobjekt med all information som behövs för att ansluta. Dba anger ip-adress, dbp anger port, dbi anger vilket SID som skall användas, u är avändarnamn och p är lösenord. dbConnect() Ansluter till databasen
dbDisconnect() Kopplar från anslutningen getResultSet() Returnerar databasens svar som ett ResultSet.
getResult(String s) Returnerar svaret som en stringarray. S anger vilken kolumn som skall hämtas. dbQuery(String vars, String table, String
order)
Skapar databasfråga med kolumnnamn, tabell och sortering som inparametrar. dbQuery(String vars, String table) Skapar databasfråga med kolumnnamn, tabell som inparametrar. dbQuery(String sql) Skapar databasfråga med hela SQL-strängen som inparameter. insertRow(String tbl, String value)
Lägger till en rad i databasen. Tbl anger vilken tabell som skall ändras, och value vilken information som skall skrivas. isRsEmpty() Returnerar true om databasens svar är tomt.
Nedan följer huvudklassens relation till de andra klasserna.
2.5.3 Databaskonstruktion
På följande sätt skapades de tre tabeller som används av programmet. Tabellerna är skapade
med hjälp av SQL*Plus, som är ett databashanteringsprogram i Oracles programpaket.
CREATE TABLE JourId ( id NUMBER(6) PRIMARY KEY, datum VARCHAR2(10), tid VARCHAR2(5), prodavd VARCHAR2(40), anmalare VARCHAR2(40), registrerare VARCHAR2(40) );
CREATE TABLE JourPersonal ( id NUMBER(6), anstnr NUMBER(5), namn VARCHAR2(30), org VARCHAR2(10), kallad VARCHAR2(17), ank VARCHAR2(17), klar VARCHAR2(17), tid VARCHAR2(5), lonetid VARCHAR2(5), biltaxi VARCHAR2(4) );
CREATE TABLE JourOrder ( id NUMBER(6), aonr NUMBER(6), objid VARCHAR2(20), beskrivning VARCHAR2(50), skapad VARCHAR2(25), arbetsbeskrivning VARCHAR2(150) );
Kolumnerna definieras genom att först skriva namn följt av vilken typ av värden som
kolumnen skall innehålla. Följande typer är använda i databasen.
• NUMBER(n) Heltalsvariabel
med
n teckens längd.
NUMBER(3) betyder t.ex. ett tal mellan 0 och 999.
• VARCHAR2(n)
En textsträng med n teckens längd.
VARCHAR2(5) betyder t.ex. att maximalt antal tecken i
strängen får vara fem.
• PRIMARY KEY
Egentligen ingen datatyp, utan mer en begränsning på hur
kolumnens innehåll får bete sig. Om kolumnen är märkt
PRIMARY KEY måste dess innehåll vara unikt och skiljt
från NULL
5.
5
NULL är inte noll, även om det kan liknas med värdet noll. NULL är inget värde, det är ett tillstånd. Därför
2.5.4 Konvertering till Applet
Fram tills nu är klasserna och funktionerna testade i små applikationer. Detta för att det är
enklare att provköra en applikation. Det är nu dags att sammanfoga dessa i det som skall
komma att bli själva programmet. Till en början uppstod inga direkta problem. Allt fungerade
tills databasklassen skulle implementeras – då uppstod ett stort problem som ingen hade tänkt
på.
Precis som nämnts tidigare hindrar appletens säkerhetsrestriktioner anslutningen till
databasen. Programutvecklingen avstannade helt, och övergick till febril felsökning. Eftersom
denna säkerhetsaspekt hade undgått oss båda blev den första uppgiften att ta reda på vad som
orsakade felet. Det hade lika gärna kunnat vara ett konverteringsfel som något annat. Efter två
dagars informationssökning visade sig problemet vara just säkerheten. När väl felet var
identifierat hittades snabbt tre möjliga lösningar.
1. Signerad Applet
2. Oracle Connection Manager
3. Börja om, och utveckla en vanlig applikation istället
Eftersom val tre inte ens var att tänka på, lades all tid på att försöka lösa problemet genom
någon av de två första valen. Signerad applet utvärderades först. Det visade sig att detta sätt
helt tog bort säkerhetsrestriktionerna. Dessvärre visade det sig att det var totalt omöjligt att
göra en fungerade signerad applet. Varje version av javatolk och varje webbläsare hade sitt
eget sätt att signera appleten, och de var inte kompatibla med varandra. Ljuset släcktes när vi,
efter många lästa foruminlägg på Suns egen webbplats, plötsligt såg rubriken: ”SIGNED
APPLET – FORGET ABOUT IT!!!!!”. Det var alltså uppenbart att det var fler som hade
väldiga problem med detta.
Nu lades all krut på att få igång en fungerande Connection Manager. Gösta Nilsson, som är
systemansvarig för teknisk service, konsulterades. Han bidrog med installationsskivor för
Oracles Connection Manager, nu fattades bara konfigureringen. Eftersom ingen av oss hade
kunskaper om Oracles program blev första delmomentet att studera diverse litteratur i ämnet.
Efter många tester och misslyckade konfigurationer hittades tillslut en fungerande variant.
Problemet var nu äntligen löst, efter ganska precis en veckas intensivt arbete, och
utvecklingsarbetet kunde därmed fortskrida.
2.5.5 Design
Fig. 8: Gränssnitt 1 (Startsidan)
Gränssnitt ett består av två tabeller. I den övre tabellen är det meningen att användaren skall
fylla i uppgifter om det nya jourtillfället, så som produktionsavdelning, vem som utfärdat
arbetsordern samt vem som registrerat den. All information lagras i comboboxar. Kontrollen
av inmatad data blir då obefintlig, och överblicken av de olika valen blir enklare.
Fig. 9: Gränssnitt 1 med exempel på en combobox.
Den andra tabellen är en översiktstabell, som listar alla jourtillfällen mellan två valbara
datum. Detta gör att det blir väldigt lätt för användaren att ha en bra översikt över vilka
jourtillfällen som skapats. När programmet startar visas det senaste dygnets jourtillfällen. Det
är möjligt att dubbelklicka på valfri rad i översiktstabellen för att visa det markerade
jourtillfället som en ny flik.
När användaren skapar ett nytt jourtillfälle, eller öppnar ett befintligt, visas gränssnitt två i en
egen flik. Fliken får sitt namn från jourtillfällets kreationsdatum och tid, samt vilken
produktionsavdelning som angetts. Om flera tillfällen är öppna samtidigt blir det, på detta sätt,
lättare att navigera till rätt flik.
Fig. 10: Gränssnitt 2
Gränssnitt två består av tre tabeller, och två knappar. Tabell ett innehåller samma information
som ges vid skapandet av ett jourtillfälle inklusive datum och tid. Denna tabell går inte att
redigera. Tabell två håller reda på vilken personal som blivit utkallad under det aktuella
jourtillfället. Användaren behöver bara skriva in anställningsnummer, resten av fälten fylls då
i automatiskt.
Fig. 11: Inmatning av anställningsnummer utan att trycka enter.
Fig. 12: Efter enterslag fylls de övriga fälten i automatiskt.
Anställningsnumret matchas mot IFS och rätt namn skrivs in i namn-kolumen. Samtidigt som
detta görs fylls även kallad, ankomst och klar med aktuellt datum och tid. Tid och lönetid
beräknas utifrån ankomst och klar, lönetiden underskrider aldrig tre timmar. Den sista
kolumnen visar bil som default, men kan ändras till taxi via en combobox. Ankomst och klar
skall sedan ändras när den utkallade anmäler sig i vakten och när arbetet är utfört. Detta kan
göras helt manuellt, men enklast genom att markera och dubbelklicka (eller trycka CTRL+T)
Tabell tre fungerar på samma sätt som föregående, men istället för anställningsnummer
skriver användaren in arbetsordernumret. Diverse information om arbetsordern hämtas från
IFS och visas i tabellen.
Fig. 13: Inmatning av arbetsordernummer utan att trycka enter.
Fig. 14: Efter enterslag fylls de övriga fälten i automatiskt.
För att datorn skall känna av när ett fält ändrats och därefter utföra önskade åtgärder behövs
en lyssnare, i ovanstående fall en TableChangeListener. Lyssnaren fungerar inte på alla
tabeller i programmet, utan behöver kopplas till de tabeller som den skall verka på.
TabledefautModel m = new TableDefaultModel(); JTable t = new JTable(m);
. .
t.addTableModelListener(this); //här koppas lyssnaren till tabellen t. .
. .
//Hit hoppar programmet när det sker en ändring i tabellen t. public void tableChanged(TableModelEvent e)
{
//här sker de åtgärder som skall utföras vid ändringen. }
I ovanstående fall behövs lyssnaren bara när något ändras i första kolumnen (kolumn 0). Om
något t.ex. ändras i kolumnen ”ankomst” kommer programmet att försöka hämta personaldata
igen, och ett fel uppstår. Därför har en begränsning lagts till som ser till att endast koden
utförs när kolumn 0 är markerad.
public void tableChanged(TableModelEvent e) {
int column = e.getColumn(); //hämtar markerad kolumn
if (column==0) //ser till att det är kolumn 0 som är markerad {
//här sker de åtgärder som skall utföras vid ändringen. }
2.5.6 Flikhantering
Användandet av fliksystem skapar vissa problem. Varje flik blir en egen arbetsyta med sina
egna komponenter, så som knappar och tabeller. När en ny flik skapas måste den alltså fyllas
med nya knappar och tabeller. Från början sparades tabellerna i en array och knapparna i en
annan array. Vid skapandet läggs då t.ex. knappen spara i position noll i array 1 och tabell ett
i array 2. I och med det har de samma position i arrayerna och det är lätt att hålla reda på vad
som hör ihop. Om ytterligare en ny flik skapas så sker samma process, men det lagras på
nästa position istället.
Fig. 15: Tabeller och knappar för flik 1 lagras i respektive array med samma index.
Problemet är att programmeraren måste bestämma hur många flikar som får skapas. Så länge
användaren inte överskrider det antalet är det inga problem. Skulle användaren däremot skapa
fler flikar än förutbestämt kommer det att uppstå ett fel. Programmet inte vet var den ska lagra
informationen.
Lösningen på problemet är att använda sig av en vektor. En vektor bygger på samma princip
som en array, men istället för att i förväg bestämma storleken, skapas en ny position allt
eftersom det behövs. Datorns arbetsminne begränsar nu hur många flikar som kan skapas. Det
betyder i stora drag att det inte finns någon begränsning, då flikarna inte tar upp så mycket
minne samt att arbetsminnet oftast är väldigt stort. Ett annat problem som uppkommer är att
det nu t.ex. kan finnas tio stycken spara-knappar i en vektor. Hur skall programmet veta
vilken knapp som är nedtryckt? Om knappen inte finns lagrad i en vektor, utan är ”ensam”,
används följande kod för att ta reda på om den blivit nedtryckt:
//Knapplyssnaren
public void actionPerformed(ActionEvent e) {
//Lägger "klickad" knapp i o Object o = e.getSource();
//Knappen Skapa Nytt if (o==gr1_btnSkapa) {
//Här sker det som skall utföras när man klickar på knappen! } }
Array 2 0 1 2 3 4 5 6 7 8 9 10 0 1 2 3 4 5 6 7 8 9 10 Array 1 Flik 1
Det går tyvärr inte att göra på samma sätt när knappen ligger i en vektor. Den första lösningen
på problemet var att göra en for-sats som loopade igenom hela vektorn och jämförde alla
knappar. Detta fungerade, men kanske inte var den bästa lösningen. Eftersom flik-index hör
ihop med vektorernas index, borde det gå att ta hjälp av vilken flik som är aktiv för att veta
vilken knapp som tryckts ner. Flik-hanteraren har en medlemsfunktion som heter
getSelectedIndex(), funktionen returnerar den aktiva flikens positionsnummer. I och med att
den första fliken alltid är öppen (gränssnitt ett), så kommer alltid det första jourtillfället att få
flik-index ett. Därför subtraheras ett från getSelectedIndex() för att hamna på rätt position i
vektorerna
//Knapplyssnaren
public void actionPerformed(ActionEvent e) {
//Lägger "klickad" knapp i o Object o = e.getSource(); //Knappen Klar if (jtp.getSelectedIndex()-1>=0) if (o==gr2_btnKlar.get(jtp.getSelectedIndex()-1)) {
//Här sker det som skall utföras när man klickar på knappen! }
}
Varje gång en knapp trycks ner hoppar programmet till funktionen actionPerformed. Varje
knapp i funktionen motsvarar en if-sats, som synes i ovanstående kod. Eftersom den första
fliken har index 0 måste det finnas en kontroll att inte indexet blir -1 då användaren befinner
sig där. Om användaren t.ex. trycker på ”Öppna Jourtillfälle” kommer getSelectedIndex() att
returnera noll, eftersom första fliken är aktiv. Programmet kommer ändå att kontrollera alla
andra knappars if-satser i funktionen actionPerformed. Därför behövs en kontroll att inte
indexet blir negativt, vilket görs i den första if-satsen i koden ovan.
När användaren trycker på knappen klar så stängs fliken, men den är egentligen bara stängd
visuellt. I minnet ligger fortfarande alla komponenter som tillhör fliken kvar, därför måste
även flikens komponenter ”stängas”. Detta görs genom att frigöra de positioner i vektorerna
som inte längre behövs.
//Hämtar aktuellt position
int index = jtp.getSelectedIndex()-1; //Frigör minnesutrymme gr2_tblId.removeElementAt(index); . . .
Variabeln index är som tidigare nämnts den variabel som håller reda på vektorns position,
m.h.a. vilken flik som är vald. Medlemsfunktionen removeElementAt(n) raderar position n
från vektorn och frigör minnet.
2.5.7 Test och justeringar
Efter sju veckors programmering har en fungerande applet växt fram. Det är nu dags att
testköra och visa handledaren Rickard Klingberg appleten. Givetvis är inte programmet
perfekt från början, vissa detaljer behöver självklart finslipas. Efter testkörning gjordes
följande förbättringar:
Anst.nr. och AO.nr. får bara finnas en gång per jourtillfälle. Vid inmatning av
anställnings- och arbetsordernummer, skall det kontrolleras att samma nummer inte finns med
tidigare i listan. Detta löstes på följande sätt:
int r = pers.getSelRow()-1; if (r>=0) { String s = (String)pers.getCellValue(r+1,0); while (r>=0) { if (pers.getCellValue(r,0).equals(s)) {
//Om numret finns raderas den nya raden }
r--; }
}
Den inmatade radens nummer jämförs med alla ovanstående rader. Om numret hittas raderas
den senast inmatade raden. En dialogruta gör användaren uppmärksam på att numret redan
finns i listan.
Inga tomma rader mellan personal och arbetsorder. I och med att tabellerna innehåller
elva fasta rader, kommer det förr eller senare att uppstå problem, då användaren skriver på fel
rad. D.v.s. det finns en eller flera tomma rader mellan posterna. Dels blir tabellerna
svåröverskådliga, samt att det blir problem när data skall sparas till databasen.
Sparafunktionen avbryts nämligen när en tom rad påträffas.
//Ser till att det inte finns tomma rader mellan posterna public void emptyRowsBetween(JTableControl p,int fr) {
while (fr>=0 && p.getCellValue(fr,0)=="") { p.deleteRow(fr); p.addEmptyRow(1); fr--; } }
Funktionen söker efter tomma rader ovanför den nya inmatningen och avbryter när den träffar
på en cell som innehåller data. Varje tom rad som påträffas raderas och en ny rad läggs till sist
i listan, på så sätt flyttas den inmatade raden upp ett steg. Detta utförs tills det inte finns några
tomma rader kvar.
Infoga en extra rad. För att inte begränsa programmet finns det möjlighet att utöka antalet
rader i personal- och arbetsordertabellerna utöver de elva rader som redan finns. Med ett tryck
på insert utökas tabellen med en extra rad, detta kan givetvis upprepas önskat antal gånger.
Problem vid radering av rad. Från början var Personal- och arbetsordertabellerna kopplade
till en lyssnare, som triggar på alla ändringar. Detta gick bra så länge användaren skrev in
information på en befintlig rad, men om en rad togs bort eller lades till uppstod ett problem.
Det var inte meningen att lyssnaren skulle trigga vid dessa tillfällen. Lite efterforskning gav
oss tre händelser som utlöser lyssnaren – UPDATE, INSERT och DELETE. Därför
begränsades tabellyssnaren till att enbart lyssna på UPDATE-händelser. På så sätt undviks
problemet, eftersom att lägga till eller ta bort en rad inte är någon UPDATE-händelse.
//Körs om det sker en ändring i en tabellcell public void tableChanged(TableModelEvent e) {
if (e.getType() == TableModelEvent.UPDATE) {
//Här utförs allt som skall ske när en cell ändras }
}
Det skall inte gå att öppna tomma eller ”omarkerade” rader. Många funktioner kräver att
en cell skall vara markerad för att fungera. Det går tyvärr att komma åt dessa funktioner utan
att någon cell markerats. Om detta sker kommer programmet peka på en ogiltig minnesadress
och därefter krascha. För att undvika att hela programmet kraschar fångas dessa händelser upp
m.h.a. en try/catch sats.
try {
//Här utförs kod som kan orsaka t.ex. minnesfel. }
catch (Exception e) {
//Om det blir fel i try-satsen kommer det att fångas upp i //efterförljande catch som i sin tur kan visa en varningsruta,
//istället för att krascha hela programmet. }
På detta sätt löses många av de kritiska kodrader som finns i programmet. Ett annat sätt är att
se till att aldrig hamna i dessa situationer. I detta fall returnerar getSelRow() minus ett om
ingen rad är markerad, då går det också bra att göra på nedanstående sätt.
int sel = order.getSelRow(); if (sel!=-1)
{
//Utför ändringar på markerad rad. }
else {
//Felutskrift om ingen rad är markerad. }
3 Resultat
Vi har valt att endast behandla jourappleten i denna rapport, men vi har även utvecklat en
rapportapplet. Den är nästan identisk med jourappleten och den enda skillnaden är att det inte
går att skapa nya jourtillfällen i den. Rapportappleten är endast till för att det skall gå att söka
bland bokförda jourtillfällen.
3.1 Slutsatser
Vi lyckades kringgå appletens säkerhetsrestriktioner och öppna en socket mot en annan dator,
i detta fall en databas. Och därmed skapa en koppling mellan databaserna och appleten. Vi
använde också comboboxar istället för att använda vanlig inmatning vid skapandet av ett nytt
jourtillfälle, vilket gjorde att felkontrollen blev minimal. Flikar istället för fönster är att
föredra, eftersom hanteringen blir lättare och mer kontrollerat. Dessa är de mest väsentliga
slutsatserna vi kan dra angående programmet, men vi vill även poängtera strukturen och
arbetsgången.
Det hade varit bättre att arbeta med applets hela tiden, istället för som vi gjorde i början,
skriva små applikationer. Resultatet hade ändå blivit den samma, men vi hade kanske undvikt
en del problem istället.
Att börja med att utveckla de funktioner och klasser som skall användas, för att sedan bygga
ett programskal, visade sig vara ett bra arbetssätt. Arbetet blir mer strukturerat. Det blir även
lättare att gå vidare och bygga på programmets funktioner allt eftersom. Ett program skall inte
bara vara en fungerande enhet. Det skall även vara relativt lätt för någon annan att sätta sig in
i, och skriva egna modifieringar. Utan struktur och kommenteringar blir det annars tämligen
värdelöst på längre sikt.
3.2 Rekommendationer för fortsatt arbete
Jourappletens webbsida bör på något sätt lösenordsskyddas. Som det är nu kommer alla som
känner till adressen åt appleten, och kan lägga till egna jourtillfällen. Meningen är att endast
vakten skall ha access till denna sida. Detta löses enklast genom att lösenordsskydda
webbsidan på servern, vilket lätt kan åtgärdas av administratören.
Det pratas mycket om ergonomi i dagens samhälle. Under slutfasen av arbetet fick vi reda på
att allt fler på företaget klagar på krämpor i arm och handled – s.k. musarm. Vi kanske borde
tänkt på att programmet skall gå att styra enbart med tangentbordet om så önskas. I och för sig
tror vi att användaren avsätter högst fem till tio minuter i sträck framför programmet. Därför
kommer inte detta påverka användaren nämnvärt. Det är viktigare att användarens
datorrutiner ses över. En paus på 2 minuter varje timme, där användaren sträcker på sig och
mjukar upp leder, räcker för att undvika förslitningar.
4 Referenslista
4.1 Tryckta källor
Jan Skansholm och Studentlitteratur 1998, 2003 , Java Direkt med Swing (fjärde upplagan),
Lund, Studentlitteratur, ISBN 91-44-04254-X
Magnus Merkel, 1999, Tekniska Rapporter och Examensarbeten, Linköping, Linköpings
Universitet
4.2 Elektroniska källor
http://www.javaalmanac.com/
http://www.sun.com
5 Bilagor
5.1 Konfiguration av Oracle Connection Manager
5.1.1 cman.ora
#============================================================================== # Connection Manager config file
# cman.ora
#============================================================================== #
# cman's listening addresses #
cman = (ADDRESS_LIST=
(ADDRESS=(PROTOCOL=tcp)(HOST=webbserverns ip)(PORT=1630)) )
cman_admin = (ADDRESS=(PROTOCOL=tcp)(HOST=webbserverns ip)(PORT=1830)) #
# cman's configurable params #
# MAXIMUM_RELAYS defaults to 128 # LOG_LEVEL defaults to 0 # TRACING defaults to no
# TRACE_DIRECTORY defaults to .../network/trace # RELAY_STATISTICS defaults to no
# SHOW_TNS_INFO defaults to no # USE_ASYNC_CALL defaults to yes # AUTHENTICATION_LEVEL defaults to 0 # MAXIMUM_CONNECT_DATA defaults to 1024 # ANSWER_TIMEOUT defaults to 0 # MAX_FREELIST_BUFFERS defaults to 2048 # cman_profile = (parameter_list= (MAXIMUM_RELAYS=1024) (LOG_LEVEL=1) (TRACING=no) (RELAY_STATISTICS=yes) (SHOW_TNS_INFO=yes) (USE_ASYNC_CALL=yes) (AUTHENTICATION_LEVEL=0) (REMOTE_ADMIN=FALSE) )
5.1.2 tnsnames.ora
#Anslutning via Conection Manager till IFS CMAN_IFS.WORLD =
(DESCRIPTION = (ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = webbserverns ip)(PORT = 1630)) (ADDRESS = (PROTOCOL = TCP)(HOST = databasens ip)(PORT = 1521)) ) (SOURCE_ROUTE = yes) (CONNECT_DATA = (SERVICE_NAME = pumaprod) ) )
#Anslutning via Connection Manager till Jour-databasen CMAN_JOUR.WORLD =
(DESCRIPTION = (ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = webbserverns ip)(PORT = 1630)) (ADDRESS = (PROTOCOL = TCP)(HOST = databasens ip)(PORT = 1521)) ) (SOURCE_ROUTE = yes) (CONNECT_DATA = (SERVICE_NAME = utv_puma) ) )
5.1.3 Installationsanvisning i Windows
1. Installera Oracle Connection Manager på den server där appleten skall användas.
2. Skapa filerna cman.ora och tnsnames.ora och kopiera dem till
%ORACLEHOME%\network\ADMIN\.
3. Starta kommandotolken och skriv cmctl start. Detta kommando startar managern som en
process i operativsystemet.
4. Med kommadot tnsping <anslutning> kan anslutningarna i tnsnames.ora kontrolleras.
Om de är rätt konfigurerade kommer respektive databas att svara.
Kommandon som kan vara bra att känna till:
cmctl status visar statusen på connection managern.
cmctl shutdown avslutar connection managern.
cmctl close_relay all stänger alla aktiva anslutningar, men lämnar managern igång.
5.2 Installationsanvisning för applet
5.2.1 Färdigställande av applet
Efter kompilering av koden skall följande punkter utföras för att programmet skall fungera i
en webbläsare. Alla kommandon skrivs i kommandotolken. För att kommandona skall
fungera i alla kataloger på hårddisken, kan java-katalogens sökväg behöva läggas till i
systemet. Skriv path %path%;<sökväg för java> för att göra detta.
1. Byt till katalogen där dina klassfiler är sparade.
2. Döp om huvudfilen (den fil som appleten körs ifrån) I vårt fall blir jourapplet.class
omdöpt till jourapplet.buf.
3. Skriv jar cf paket.jar *.class, där paket.jar kan döpas till valfritt namn. Alla klassfiler
utom huvudklassen packas nu ihop i denna .jar-fil.
4. Döp nu om jourapplet.buf till jourapplet.class igen.
5. Kopiera nls_charset12.jar och classes12.jar från java-katalogen till katalogen där dina
klassfiler är sparade. Dessa behövs för att kopplingen till databasen skall fungera.
6. Skapa en html-sida i valfritt program, t.ex. anteckningar. Se exempel som följer.
<html> <head>
<title>Bravikens Joursystem</title> </head>
<body>
<center><applet code="JourApplet.class" archive="paket.jar, nls_charset12.jar, classes12.jar" width="900" height="600"></applet></center>
</body> </html>