Uppgifter

Under dessa sidor finns uppgifterna till kursen. Innan uppgifterna presenteras så finns viktig info om allmänna krav och tips.

Allmänna krav

Allmänna tips

Uppgift 1: Äpplen, trådning och JAR-filer

Det är mycket viktigt att man kan trådning, äpplen och JAR-filer bra så vi börjar med det.

Nivå: Lätt.
Allmänt: Uppgiften går ut på att konstruera ett enkelt multi-trådat program. Det finns två sätt att göra en klass trådad på och vi övar här på båda. Det är mycket viktigt att man förstår båda dessa sätt bra eftersom några av de efterföljande uppgifterna är trådade. Trådning är en mycket vanlig och kraftfull teknik.
Info: Kapitel 1 och Lektioner.
Uppgift: Gör ett äpple (med ett grafiskt användargränssnitt) som har två knappar och en text-area. Respektive knapp ska ha texterna Aktivera utskrift från tråd 1 och Aktivera utskrift från tråd 2. Använd tre klasser:
  • En klass för äpplet (och det grafiska gränssnittet).
  • En klass för tråd 1. Denna klass ska ärva från klassen Thread.
  • En klass för tråd 2. Denna klass ska inte ärva från klassen Thread utan implementera gränssnittet Runnable.

Respektive tråd ska i en loop i run-metoden kunna skriva ut meddelandet Utskrift från tråd 1 och Utskrift från tråd 2 i programmets text-area. Utskriften ska göras en gång per sekund.

Vid tryck på den ena knappen ska tråd 1 aktiveras och texten på knappen ska ändras till Deaktivera utskrift från tråd 1. Ett tryck till på samma knapp ska deaktivera tråd 1 (det vill säga stoppa tråd 1 helt) och texten på knappen ska återställas till Aktivera utskrift från tråd 1. Motsvarande gäller för den andra knappen men för tråd 2.

De färdiga CLASS-filerna ska packas i en JAR-fil och HTML-filen som hör till äpplet ska använda denna JAR-fil.

Exempel: Ett enkelt exempel kan köras från kommandoprompten med:

appletviewer http://atlas.dsv.su.se/~pierre/i/ip1/inl/i1/threader.html

Tips: Vid implementering av gränssnittet Runnable så måste man deklarera och initiera en variabel för tråden:

Thread tread = new Thread(this);

Man måste givetvis även starta tråden (på ett lämpligt ställe) med:

tread.start();

Läs i API-beskrivningen under java.lang.Thread om varför stop-metoden med flera inte fungerar. Där finns bra tips på hur man stoppar en tråd.

Man får automatisk scrollning av en JTextArea med:

textArea.append("\n" + "T1 running");
textArea.setCaretPosition(textArea.getText().length());

Man måste göra ett nytt trådat objekt vid varje omstart, det går alltså inte att enbart köra start-metoden igen.

För den intresserade finns ett mer avancerat multi-trådat program för en enkel grafisk tillämpning, en (för datorn) svår snöstorm, brr :-), där varje snöflinga är en egen tråd. Programmet ställer dock vissa krav på hårdvaran :-). Källkoden finns här.

Uppgift 2a: URL-koppling, otolkad information

Nivå: Lätt.
Allmänt: Uppgiften belyser användandet av klassen URL.
Info: Kapitel 2, 3 och Lektioner.
Uppgift: Gör ett fristående program med ett grafiskt användargränssnitt som implementerar en enkel browser. Användaren ska kunna ange en valfri HTTP-adress i ett text-fält och programmet ska hämta informationen på denna adress och presentera resultatet i en text-area. Själva hämtningen kan initieras när användaren trycker på return i text-fältet, på en knapp eller liknande.

När programmet startar ska det hämta och presentera information från den adress som finns default i textfältet från början. Observera! Informationen ska inte tolkas utan bara presenteras som ren text.

De färdiga CLASS-filerna ska packas i en JAR-fil och denna ska gå att köra med:

java -jar Browser.jar

(se manifest).

Exempel: Ett enkelt exempel kan köras enligt följande:
  1. Hämta filen: Browser.jar
  2. Kör programmet med: java -jar Browser.jar
Tips: Använd klassen URL och någon lämplig metod för ett objekt från denna klass, exempelvis metoden openStream vilket returnerar i en in-ström som man kan läsa från.

I nästa uppgift skall vi bygga en browser som kan tolka den information vi hämtar.

Uppgift 2b: URL-koppling, tolkad information

Nivå: Lätt.
Allmänt: Uppgiften visar ett alternativt sätt att bygga en browser på.
Info: Kapitel 2, 3 och Lektioner.
Uppgift:

Gör samma sak som i Uppgift 2a men med följande modifikationer:

  • Programmet ska vara ett äpple.
  • Den mottagna informationen ska tolkas, det vill säga inte enbart presenteras som ren text, och länkarna ska fungera.

Notera att det nu, av säkerhetsskäl, endast går att göra uppkopplingar till samma domän som äpplet laddades ner från. Mer om detta på kursen Internetsäkerhet.

De färdiga CLASS-filerna ska packas i en JAR-fil och HTML-filen som hör till äpplet ska använda denna JAR-fil.

Exempel: Ett enkelt exempel kan köras från kommandoprompten med:

appletviewer http://atlas.dsv.su.se/~pierre/i/ip1/inl/i2/browser_cool.html

Tips: Använd klassen javax.swing.JEditorPane (se API-beskrivningen).

Man kan testa sitt äpple under utvecklingen på två sätt. Man kan surfa till:

  • En fil lokalt på samma dator:
    • Protokoll: File.
    • Säkerhet: Filen måste komma från samma katalog som äpplet.
    • Exempel: file:///C:/Documents and Settings/Administrator/My Documents/en_fil.txt
  • En fil via en http-server från en annan dator:
    • Protokoll: HTTP.
    • Säkerhet: Filen måste komma från samma domän som äpplet. Notera att man då måste lägga ut äpplet på nätet under denna domän.
    • Exempel: http://atlas.dsv.su.se/

Försöker man ladda en fil utanför det område beskrivet ovan så genereras en Sequrity Exception.

För den intresserade så finns ett komplett Java-paket här som man kan använda om man någon gång behöver en ännu mer avancerad browser (som tolkar informationen) i ett Java-program. Det fungerar utmärkt och är mycket lätt att använda.

Uppgift 3a: Klient-server klient-sidan, TCP, stream sockets

I Uppgift 2 kopplade vi oss till en speciell typ av server, en HTTP-server, ofta även kallad en webb-server. Vi ska i nästa uppgift koppla oss på ett mer generellt sätt till en server, i detta fall till en chat-server. Vi ska, så att säga, arbeta på en lägre nivå. Detta är ofta mycket användbart och man får mycket större frihet i vad man kan göra. Uppgift 3a och 3b är något svårare men det är mycket viktigt att man kan detta bra.

Nivå: Medel.
Allmänt: Uppgiften belyser användandet av stream sockets på klient-sidan.
Info: Kapitel 2, 3 och Lektioner.
Uppgift: Gör ett fristående program med ett grafiskt användargränssnitt som implementerar en chat-klient som kan sända och ta emot text-meddelanden. Chat-klienten ska koppla upp sig till en chat-server via en stream-socket. När en chat-klient sänder ett text-meddelande till chat-servern så sänder chat-servern detta text-meddelande till alla anslutna chat-klienter. Chat-klienten ska alltså både kunna:
  • Sända text-meddelanden (inskrivet i exempelvis ett text-fält) till chat-servern.
  • Ta emot text-meddelanden från chat-servern och visa dessa text-meddelanden i en lämplig swing-komponent, exempelvis en text-area.

Chat-klienten ska gå att startas på tre sätt:

  1. java Client (då ska host default bli 127.0.0.1 och port default bli 2000)
  2. java Client <host> (då ska port default bli 2000)
  3. java Client <host> <port>

Efter detta ska chat-klienten försöka koppla sig till chat-servern. Om kopplingen lyckas så ska det i chat-klientens titelrad stå vilken server och port man är uppkopplad till. Om kopplingen inte lyckas så ska programmet avslutas.

De färdiga CLASS-filerna ska packas i en JAR-fil och denna ska gå att köra med:

java -jar Client.jar

(se manifest).

Verktyget javadoc ska användas för beskrivningen av denna uppgift.

Exempel: Ett enkelt exempel kan köras enligt följande:
  1. Hämta filen: Client.jar
  2. Kör programmet med: java -jar Client.jar

Observera! Chat-servern måste vara igång innan man startar chat-klienten, se Uppgift 3a / Tips.

Observera! När man använder Netscapes browser för nerladdning så fungerar inte Client.jar och Server.jar. Vi har tyvärr inte löst detta konstiga problem men här finns en ZIP-fil med de viktigaste filerna.

Tips: För att testa klienten kan man antingen:
  • Hämta denna chat-server: Server.jar och starta chat-servern med:

java -jar Server.jar

Med detta kommando startar chat-servern på port 2000 men man kan även ange ett annat portnummer, exempelvis:

java -jar Server.jar 2001

Man kan testa att chat-servern fungerar med: telnet 127.0.0.1 2000

  • Köra chat-servern mot host: atlas.dsv.su.se på port: 9494. Denna chat-server kan då och då gå ner av överbelastning och man kan testa om den är igång med: telnet atlas.dsv.su.se 9494.

Använd klassen Socket och metoderna getInputStream och getOutputStream för att få strömmar att läsa och skriva från. Exempel på lämpliga ström-kopplingar:

in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);

Klienten måste vara multi-trådad. Hämtningen av meddelanden från servern bör ligga i en evig loop i metoden run.

Chat-servern implementerar ett minimalt protkoll som man kan leka med. Om en chat-klient skickar wwhhoo så returnerar chat-servern alla uppkopplade chat-klienters IP-adresser (den inleder svaret med WWHHOO: för varje chat-klient). En chat-klient som utnyttjar detta för att visa uppkopplade chat-klienter är den som används under Hjälp/Chat. Vi har i denna även implementerat ett filter som sorterar ut meddelanden som inte kommer från respektive kurs.

Det finns en JDK-extension kallad Java Media Framework (JMF) som möjliggör att man kan koppla programmen till datorns mikrofon, kamera, vidoekamera med mera och sända data från dessa saker över nätet (både i klump och streamat). En närmare titt här. Med detta API kan man ju göra enormt intressanta tillämpningar, exempelvis ett video-baserat chat-program.

Uppgift 3b: Klient-server server-sidan, TCP, stream sockets

Nivå: Svår.
Allmänt: Uppgiften belyser användandet av stream sockets på server-sidan.
Info: Kapitel 2, 3 och Lektioner.
Uppgift: Gör ett fristående program med ett grafiskt användargränssnitt som implementerar en chat-server som kan sända och ta emot text-meddelanden. Chat-servern ska använda stream-sockets.

Chat-servern ska kunna ta emot begäran om uppkoppling från nya chat-klienter och placera alla chat-klienter i en egen tråd för att kunna ta emot ytterligare chat-klienter. Varje chat-klient-tråd ligger och väntar på att en chat-klient ska skicka ett text-meddelande. När så sker så ska chat-servern "broadcasta" detta meddelande till samtliga chat-klienter. Chat-servern måste således hålla reda på alla anslutna chat-klienter i någon datasamling.

Alla text-meddelanden som sänds från chat-klienterna ska visas en en lämplig swing-komponent, exempelvis en text-area. För samtliga text-meddelanden så ska följande skrivas ut i denna swing-komponent:

  • Chat-klientens IP-adress.
  • Text-meddelandet från chat-klienten.

Chat-servern ska gå att starta på två sätt:

  1. java Server (då ska port default bli 2000)
  2. java Server <port>

Efter detta ska chat-servern göra sig redo för att ta emot förfrågningar om anslutning från chat-klienter. Om detta lyckas så ska det i chat-serverns titelrad stå den host och port som chat-servern kör på samt antalet chat-klienter som är uppkopplade.

Observera! Chat-servern ska upptäcka när en klient inte längre är ansluten och då ta bort den ur datasamlingen och döda tråden (eventuellt kan tråden döda sig själv).

De färdiga CLASS-filerna ska packas i en JAR-fil och denna ska gå att köra med:

java -jar Server.jar

(se manifest).

Verktyget javadoc ska användas för beskrivningen av denna uppgift.

Exempel: Se chat-servern som användes i Uppgift 3a.
Tips: Använd klassen ServerSocket och metoden accept.

Man måste vara försiktig med krockar. Man har ju ofta flera trådar igång för hantering av anslutna chat-klienter och det kan exempelvis bli fel om man samtidigt (1) tar bort en chat-klient-tråd och (2) broadcastar ett meddelande. För att lösa detta bör man deklarera vissa metoder i chat-servern som synchronized.

Hur upptäcker chat-servern att en chat-klient har kopplat ner? För varje chat-klient som kopplar upp sig till chat-servern så skapar chat-servern en egen tråd för chat-klienten. Antag att klassen som hanterar chat-klienterna heter ClientHandler. ClientHandler är en tråd som hela tiden ligger och lyssnar på om klienten har skickat något meddelande. Om ett meddelande kommer från en chat-klient så anropar ClientHandler en metod i chat-servern som broadcastar meddelandet till alla anslutna chat-klienter. Det är i denna lyssningsfas som ClientHandler kan upptäcka om en klient har kopplat ner:

  1. Om chat-klienten beter sig korrekt och stänger sin utström returnerar läsning med (BufferedReader) readLine-metoden null.
  2. Om chat-klienten inte beter sig korrekt och inte stänger sin utström blir det IOException vid läsning med (BufferedReader) readLine-metoden.

Man får då undersöka dessa båda fall och om något av dem uppstår så ska man gå ut ur den "eviga" lyssnar-loopen, exempelvis:

public void run() {
   String msg;
   try {
      while ((msg = reader.readLine()) != null) {
         //... gör något med msg ...
      }
      writer.close();
      reader.close();
      socket.close();
   } catch (IOException e) {
   }
   server.killThread(this);
}

Precis efter try-blocket ligger satserna som stänger alla strömmar, och eftersom de genererar IOException kan de ju lika gärna ligga i try-blocket. Om ett IOException har inträffat tidigare kan man ju antagligen inte stänga strömmarna i alla fall.

Exempel på lämpliga ström-kopplingar till klient-socketen:

in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out = new PrintWriter(clientSocket.getOutputStream(), true);

Hur får man reda på server-socketens host-adress:

String host = serverSocket.getInetAddress().getLocalHost().getHostName();

Hur får man reda på klient-socketens host-adress:

String host = socket.getInetAddress().getHostName();

Uppgift 4: Peer-to-peer, UDP, datagram- och multicast-socket

I Uppgift 3 använde vi inget applikationsnivå-protokoll vilket vi ska göra i nästa uppgift. Vi ska även titta på andra typer av intressanta sockets, kallade datagram sockets, samt se hur man använder en mycket bra teknik kallad multicast. Vi ska nu inte använda klient-server paradigmen utan något kallat peer-to-peer, vilket betyder att vi inte längre använder någon central server som knyter samman allt utan allt ligger direkt hos klienterna.

Nivå: Svår.
Allmänt: Uppgiften belyser användningen av datagram sockets och multicast med peer-to-peer paradigmen.
Info: Kapitel 2, 3 och Lektioner.
Uppgift: Gör ett fristående program med ett grafiskt användargränssnitt som gör följande:
  1. Sänder upprepade text-meddelanden på en multicast-IP-adress som enbart berättar att "jag är uppkopplad nu".
  2. Tar emot text-meddelanden från en multicast-IP-adress som visar vilka som är uppkopplade nu. 

(1) Text-meddelanden som sänds ska sändas 1 gång per sekund och vara formaterade enligt ett egetkonstruerat protokoll, vi kallar det OTTP, för Online Text Transfer Protocol :-):

send(" From: " + name + " Host: " + host + " Comment: " + comment);

Här är:

  • send en egendefinierad metod som sänder meddelandet givet som argument till metoden.
  • name en variabel som anger namnet på användaren.
  • host en variabel som anger användarens host.
  • comment en variabel som anger en kommentar från användaren.

Det är viktigt att man inte sänder meddelandena oftare än 1 gång per sekund då det i UDP inte finns någon inbyggd "trafikövervakning". Sänder man med UDP för ofta kan nätverket bli överbelastat och gå ner.

(2) Text-meddelanden som tas emot ska parsas och för varje namn/host kombination så ska informationen visas på följande format så länge denna användare är uppkopplad:

name --- host --- comment

Endast en rad för varje användare ska visas.

De färdiga CLASS-filerna ska packas i en JAR-fil och denna ska gå att köra med:

java -jar OnLine.jar <name> <comment>

(se manifest). Efter detta ska programmet koppla sig till multicast-adressen 234.235.236.237 på port 2000. Om kopplingen lyckas så ska det i programmets titelrad stå vilken IP-adress (och port) uppkopplingen skett till. Om kopplingen inte lyckas så ska programmet avslutas.

Verktyget javadoc ska användas för beskrivningen av denna uppgift.

Exempel: Ett enkelt exempel kan köras enligt följande:
  1. Hämta filen: OnLine.jar
  2. Kör igång programmet med: java -jar OnLine.jar <name> <comment>

Kör gärna igång flera program på flera olika datorer. Tänk dock på att multicast är en ny teknik som för nuvarande fungerar bäst i intranät. Vill man använda denna teknik på Internet kan man använda MBone som är ett nätverk av routrar som implementerar olika multicast-protokoll.

Tips: Använd exempelvis fyra klasser:
  • En klass (OnLine) för det grafiska gränssnittet och initialiseringen av MulticastSocket.
  • En inre trådad klass (Sender) för kontinuerlig sändning av (DatagramPacket) meddelanden en gång per sekund.
  • En inre trådad klass (Receiver) för kontinuerlig mottagning av (DatagramPacket) meddelanden. Mottagna meddelanden läggs i en datasamling (exempelvis ett HashSet) om de inte finns i datasamlingen tidigare.
  • En inre trådad klass (InterfaceHandler) för kontinuerlig uppdatering av gränssnittet var 5:e sekund:
    • Töm text-arean.
    • Parsa de meddelanden som finns i datasamlingen och lägg in resultaten i text-arean.
    • Töm datasamlingen.

Har man implementerat detta med flera trådar som möjligtvis delar på någon resurs så kan krockar uppstå och man bör således deklarera vissa metoder som synchronized och/eller använda de synkroniserade datasamlingarna, exempelvis:

SortedSet ts = Collections.synchronizedSortedSet(new TreeSet());          

I exemplet har dock inget av detta använts. 

För att dela upp ett inkommet meddelande i enstaka ord så är klassen java.util.StringTokenizer utmärkt.

Notera att:

  • mulicastSocket.getInetAddress() ger värdet null,
  • mulicastSocket.getPort() ger värdet -1

och att det är som det ska, bara att gå vidare med programmeringen :-)

Man måste skapa ett nytt DatagramPacket för varje meddelande som ska tas emot.

Vi har nu bekantat oss med peer-to-peer paradigmen och vet även skillnaden mellan:

Vi vet också att man använder multicast-adresser när man vill sända saker till flera användare. Multicast är bra om vi exempelvis vill sända ut en film från en server till många tittare. Utan multicast så skulle bandbredden som krävs bli direkt proportionell mot antalet användare. Med multicast så blir bandbredden lika stor som för en enda film, oberoende av antalet tittare. En nackdel med multicast är att filmerna måste gå vissa tider, det vill säga, de levereras inte on-demand, men detta kan ju enkelt approximeras genom att sända filmen på olika multicast adresser med vissa tids-intervall.

Uppgift 5a: Välutformad XML

Nu ska vi titta på ett mycket intressant område som växer enormt fort: XML. XML är ett standard-format för data och det finns många fördelar med detta:

Java och XML är ett perfekt par!

Data givet i XML-form parsas för att kontrollera att formen stämmer enligt XML-standarden. Man kan göra denna kontroll på två sätt:

  1. Man kontrollerar att datat givet i XML-form är välformad. Detta betyder att formen ska följa den XML-standard som finns och former som uppfyller detta krav kallas för välutformade.
  2. Man kontrollerar (1) och att det följer vissa direktiv vi själva (eller någon annan) specificerat (i en så kallad DTD-form). Former som uppfyller detta strängare krav kallas valida.

Man parsar givetvis inte enbart för att kontrollera utan även för att kunna plocka isär och komma åt data i en XML-form. Tekniskt sett, under denna yta, så kan man (för nuvarande) göra parsningen på två sätt:

  1. SAX-parsning är snabb och men har inte en fullständig XML-form i minnet.
  2. DOM-parsning är långsammare men har en fullständig XML-form i minnet.

Vi kommer att använda den utmärkta parsern Xerces. Detta är en av de absolut bästa och stöder både SAX- och DOM-parsning:

The Xerces Java Parser 1.4.2 supports the XML 1.0 recommendation and contains advanced parser functionality, such as support for the W3C's XML Schema recommendation version 1.0, DOM Level 2 version 1.0, and SAX Version 2, in addition to supporting the industry-standard DOM Level 1 and SAX version 1 APIs.

De API för Java som man använder för dessa två sätt att parsa är anpassade för att fungera med flera olika språk och är ofta ganska svåra och icke-intuitiva att använda som Java-programmerare. Vi ska därför använda det allra senaste inom XML: JDOM. JDOM är ett API som ligger ovanpå SAX och DOM och som möjliggör en mycket enklare hantering av XML (med mera). Detta API integrerar mycket väl med Java och de designmönster som Java-programmerare är vana att använda. För samtliga XML-uppgifter är valet fritt om man vill använda SAX- eller DOM-parsning från JDOM.

Nivå: Lätt.
Allmänt: Uppgiften belyser begreppet välutformad XML.
Info: Lektioner. Notera att JDOM utvecklas fort och att man för säkerhets skull kontrollerar med tillhörande API-beskrivning för korrekta namn på metoder med mera.
Uppgift: Gör följande:
  • Skapa en (inte allt för enkel) välutformad XML-fil.
  • Konstruera ett program som kan kontrollera om godtyckliga filer är välutformade. Filens namn ska läsas in som argument när man startar programmet. Om filen är välutformad så ska programmet skriva ut XML-filen, annars ska programmet skriva ut vad som är fel i filen.
  • Testa programmet med den egengjorda välutformade XML-filen samt en något modifierad fil som inte är välutformad.
Exempel: Ett enkelt exempel kan köras enligt följande:
  1. Hämta filen: xerces.jar
  2. Hämta filen: jdom.jar
  3. Hämta filen: WellFormed.class
  4. Hämta filen: message_wellformed.xml
  5. Sätt classpath: set classpath=xerces.jar;jdom.jar;.
  6. Kör programmet med: java WellFormed message_wellformed.xml
Tips: Eftersom vi använder en extension till JDK så måste man göra steg 1, 2 och 5 under Exempel ovan.

Uppgift 5b: Valid XML

Vi ska nu kontrollera om den i Uppgift 5a egengjorda XML-filen är valid utifrån en egengjord DTD-fil.

Nivå: Lätt.
Allmänt: Uppgiften belyser begreppet valid XML samt hur man kommer åt enskilda element och dess barn/värden i en XML-form.
Info: Lektioner.
Uppgift: Gör följande:
  • Skapa en inte allt för enkel DTD-fil till den välutformade XML-filen i Uppgift 5a.
  • Kopiera och uppdatera XML-filen från Uppgift 5a så att den har en DOCTYPE-deklaration.
  • Konstruera ett program som kan kontrollera om godtyckliga filer är valida. Filens namn ska läsas in som argument när man startar programmet. Om filen är valid så ska programmet skriva ut varje del i XML-filen enligt följande:
    • Element med barn ska skrivas med: elementnamn och alla barnens namn.
    • Element med värden ska skrivas med: elementnamn och elementets värde.

    Om filen inte är valid så ska programmet skriva ut vad som är fel i filen.

  • Testa programmet med den egengjorda valida XML-filen samt den till denna tillhörande egengjorda DTD-filen. Testa även programmet med en något modifierad XML-fil som är välutformad men inte är valid (relativt denna egengjorda DTD-fil).
Exempel: Ett enkelt exempel kan köras enligt följande:
  1. Hämta filen: xerces.jar
  2. Hämta filen: jdom.jar
  3. Hämta filen: Valid.class
  4. Hämta filen: message_valid.xml
  5. Hämta filen: message.dtd
  6. Sätt classpath: set classpath=xerces.jar;jdom.jar;.
  7. Kör programmet med: java Valid message_valid.xml
Tips: Se Uppgift 5a/Tips.

Uppgift 5c: XML-generering

Vi ska nu titta på hur man skapar XML-former och modifierar dessa direkt i ett program.

Nivå: Lätt.
Allmänt: Uppgiften belyser XML-generering från ett program.
Info: Lektioner.
Uppgift: Gör följande:
  • Konstruera ett program som genererar exakt samma XML-fil som gjordes manuellt i Uppgift 5b (utan att läsa in denna till programmet). Den genererade filen ska sparas på en fil vars namn ska läsas in som argument när man startar programmet.
  • Testa om denna genererade fil är valid med programmet och DTD-filen från Uppgift 5b. Om inte, modifiera programmet tills den genererade filen blir valid (man upptäcker snabbt hur bra det är med DTD-filer :-).
Exempel: Ett enkelt exempel kan köras enligt följande:
  1. Hämta filen: xerces.jar
  2. Hämta filen: jdom.jar
  3. Hämta filen: Creator.class
  4. Hämta filen: message.dtd
  5. Sätt classpath: set classpath=xerces.jar;jdom.jar;.
  6. Kör programmet med: java Creator test.xml
Tips: Se Uppgift 5a/Tips.

Uppgift 5d: XML-tillämpning

Till sist ska vi använda det vi nu kan om XML för att skapa en riktig applikation. Den här uppgiften är frivillig men en av de roligaste frivilliga.

Nivå: Svår. Denna uppgift är frivillig.
Allmänt: Uppgiften belyser XML-parsning med validering, XML-generering från ett program och XML-modifikation.
Info: Lektioner.
Uppgift: Utgå från chat-klienten i Uppgift 3a för att skapa ett fristående program med grafiskt användargränssnitt som implementerar en chat-klient som använder ett protokoll. Detta protokoll skall vara formaterat i XML enligt filerna message_valid.xml och message.dtd. Programmet ska göra följande:
  • Vi sändning av meddelanden ska följande göras:
    • Klassen Document ska användas för att skapa ett XML-dokument för meddelandet. XML-dokumentet ska peka på en DTD-fil som är PUBLIC här: http://atlas.dsv.su.se/~pierre/i/ip1/inl/i5/message.dtd.
    • Klassen XMLOutputter ska sen användas för att få XML-dokumentet formaterat som en String (utan radbrytningar). Denna String ska sedan sändas på samma sätt som i Uppgift 3a.
  • Vid mottagning av meddelanden ska följande göras:
    • Meddelande ska parsas för validitet och ett XML-dokument skapas.
    • Accessa detta XML-dokument för att nå de specifika delar i XML-dokumentet som man vill visa användaren:

    <namn> (<epost>): <meddelande>

    Se Exempel under denna uppgift.

På detta sätt får vi en strikt kontroll av att de meddelanden som sänds och tas emot följer vårt protokoll och andra program som vill koppla till detta kan göra det genom att följa detta protokoll.
Exempel: Ett enkelt exempel kan köras enligt följande:
  1. Hämta filen: xerces.jar
  2. Hämta filen: jdom.jar
  3. Hämta filen: Client.class
  4. Hämta filen: Client$L1.class
  5. Hämta filen: Client$L2.class
  6. Sätt classpath: set classpath=xerces.jar;jdom.jar;.
  7. Kör programmet med: java Client

Programmet startar default mot chat-servern på: atlas.dsv.su.se port: 9494 och vill man använda en chat-server lokalt kan man starta programmet enligt Uppgift 3a samt använda chat-servern från Uppgift 3b. Notera att det ju även kan sändas meddelanden på denna "kanal" som inte följer protokollet i denna uppgift och att man då får meddelandet: KUNDE INTE PARSA ETT MEDDELANDE.

Tips: Man måste vara duktig på paketet java.io för att lösa denna uppgift, exempelvis kan man använda:

Document doc = builder.build(new StringReader(in.readLine()));

för att bygga ett XML-dokument direkt från en String.

För att konvertera ett Document till ren text utan radbrytningar är metoden setLineSeparator bra:

XMLOutputter outputter = new XMLOutputter();
outputter.setLineSeparator("");

Uppgift 6: Databaser

Nu ska vi titta på hur man kopplar sig till en databas via JDBC. Det här är också mycket roligt :-)!

Nivå: Svår. Denna uppgift är frivillig.
Allmänt: Denna uppgift belyser hur man kopplar sig till en databas-server på Internet.
Info: Kapitel 4 och Lektioner.
Uppgift: Gör ett äpple som implementerar en gästbok där användaren ska kunna fylla i följande fält:
  • Namn.
  • E-post.
  • Hemsida.
  • Kommentar.

Användarens inlägg ska sparas i databas-servern MySQL som kör på atlas.dsv.su.se. Alla inlägg ska visas i en text-area.

De färdiga CLASS-filerna ska packas i en JAR-fil och HTML-filen som hör till äpplet ska använda denna JAR-fil.

Exempel: Ett enkelt exempel kan köras från kommandoprompten med:

appletviewer http://atlas.dsv.su.se/~pierre/i/ip1/inl/i6/sql_guestbook.html

Tips:

Man behöver här ett JDBC-gränssnitt mot MySQL och det finns i följande zip-fil: twz1.zip. Packa upp zip-filen i katalogen för denna uppgift.

Anslutningen görs med:

Class.forName("twz1.jdbc.mysql.jdbcMysqlDriver");
Connection dbConnection = DriverManager.getConnection(url, username, password);

där:

url = "jdbc:z1MySQL://" + computer + "/" + db_name;
computer = atlas.dsv.su.se
db_name, username och password fås här.

När man ska skapa en JAR-fil med alla CLASS-filer från filen twz.zip med så gör man enligt följande:

jar cf SQLGuestbook.jar *.class twz1\jdbc\mysql\*.class

Använd gärna MySQLFront för att få en tydligare bild av vad som sker i databasen.

Uppgift 7a: E-post, sändning

Nu tittar vi lite på e-post, vi börjar med sändning.

Nivå: Svår. Denna uppgift är frivillig.
Allmänt: Denna uppgift belyser hur man implementerar sändning av e-post.
Info: Lektioner.
Uppgift:

Gör ett fristående program med ett grafiskt användargränssnitt som med hjälp av JDK-extensionen Javamail kan sända e-post. Användaren ska kunna skriva in följande:

  • Mail-server.
  • Från.
  • Till.
  • ämne.
  • Meddelande.
Exempel: Ett enkelt exempel kan köras enligt följande:
  1. Hämta filen: activation.jar
  2. Hämta filen: mail.jar
  3. Hämta filen: MailSender.class
  4. Hämta filen: MailSender$L.class
  5. Sätt classpath: set classpath=activation.jar;mail.jar;.
  6. Kör programmet med: java MailSender
Tips: Eftersom vi använder en extension till JDK så måste man göra steg 1, 2 och 5 under Exempel ovan. 

Uppgift 7b: E-post, mottagning

Nu fortsätter vi med mottagning.

Nivå: Svår. Denna uppgift är frivillig.
Allmänt: Denna uppgift belyser hur man implementerar mottagning av e-post.
Info: Lektioner.
Uppgift:

Gör ett fristående program med ett grafiskt användargränssnitt som med hjälp av JDK-extensionen Javamail kan mottaga e-post. Användaren ska kunna skriva in följande:

  • Mail-server.
  • Användare.
  • Password.
Exempel: Ett enkelt exempel kan köras enligt följande:
  1. Hämta filen: activation.jar
  2. Hämta filen: mail.jar
  3. Hämta filen: MailReceiver.class
  4. Hämta filen: MailReceiver$L.class
  5. Sätt classpath: set classpath=activation.jar;mail.jar;.
  6. Kör programmet med: java MailReceiver
Tips: Se Uppgift 7a/Tips.

Uppgift 8: Distribuerade processer

Vi ska nu, till sist, titta på något verkligt intressant: hur man hos en klient kan använda ett eller flera objekt som egentligen "lever" på ett annat ställe. Hos klienten kan man använda objektet precis som man brukar göra när det "lever" lokalt. Flera olika objekt kan även "leva" på flera olika ställen. Det här är lite krångligt i början men blir snabbt kul!

Nivå: Svår. Denna uppgift är frivillig.
Allmänt: Denna uppgift belyser distribuerade processer med ett exempel där man delar upp ett program i två delar och låter de mer krävande delarna i programmet köra på server-sidan.
Info: Kapitel 5 och Lektioner.
Uppgift:

Gör ett program som beräknar något krävande på serversidan med hjälp av RMI.

Man behöver bara testa detta lokalt på en och samma maskin men det är extra kul om man verkligen kör på två olika maskiner.

Exempel: Ett exempel med Mandelbrots mängd kan köras enligt följande:
Tips: Var väldigt noga och tänk minimalistiskt :-) det blir lätt fel annars.

Uppgift 9: Gesällprov

Och nu en uppgift för den egna kreativiteten:

Nivå: Om du är osäker på om din idé till gesällprov är tillräckligt omfattande så skriv e-post hit och fråga.
Allmänt: Gesällprovet är ett fritt valt (men obligatoriskt) arbete där du får chansen att visa vad du går för konstruktionsmässigt (istället för minnesmässigt som på en tenta) i "lugn och ro".
Info: Se de tidigare uppgifterna.
Uppgift: Följande krav måste uppfyllas:
  • Gesällprovet ska baseras på de tekniker som denna kurs bygger på men får givetvis även innehålla tekniker från andra områden. 
  • Gesällprovet måste vara nätverksbaserat.
  • Gesällprovet ska vara bra både till både form och funktion, det vill säga både till utseende och beteende.
  • Gesällprovet ska beskrivas generellt på en separat HTML-sida. Det ska finnas bilder på programmet under körning och dessa bilder ska beskrivas med text. En bild av ett program under körning fås (i Windows) genom att trycka på <CTRL><ALT><PRINT SCRN> samtidigt, vilket medför att bilden på programmet läggs i urklippsbufferten som sedan lätt kan klistras in i ett HTML-dokument i en HTML-editor.
  • Gesällprovet ska beskrivas med verktyget javadoc.
  • Gesällprovet kan vara ett fristående program eller ett äpple.

Med gesällprovet deltar man (frivilligt) i en tävling. De bästa resultaten kommer att presenteras på nätet och vinnaren till första deadline erhåller ett pris.

Tips: Man kan göra ett helt nytt arbete eller bygga vidare på tidigare uppgifter. Några förslag:
  • Multicast:
    • Göra ett multicast-program som fungerar över Internet med hjälp av MBONE [Medel].
  • News:
    • NNTP-klient för att hämta news [Medel].
    • NNTP-server för att serva news [Svår].
  • E-post:
    • Ett komplett e-post system som kan sända/ta emot bifogade filer med mera [Svår].
    • Mail2Phone: ett program på server-sidan som med jämna mellanrum (med hjälp av crontab) kopplar sig till en mail-server och sänder nya brev vidare till en mobiltelefon [Svår].
  • Java Micro Edition (J2ME):
    • Något med inbyggda system [Svår].
  • Spel:
    • Ett roligt nätverksbaserat spel [Svår].
    • En nätverksbaserad cellulär automat [Går det :-)?].

Det finns även en rad andra intressanta extensions som vi inte har nämnt tidigare, en bra utgångspunkt för dessa finns här.

Använd gärna chat-servern på atlas.dsv.su.se port 9494 för gesällprovet.

Huvudsaken är att man gör något som är kul!

Uppgifterna är gjorda av © Pierre A. I. Wijkman DSV 2001 och är skyddade av lagen om upphovsrätt.